libpruio  0.0.2
AM33xx-PRU driver for digital input / output and analog input
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
stepper.c
Go to the documentation of this file.
1 /*! \file stepper.c
2 \brief Example: control a stepper motor.
3 
4 This file contains an example on how to use libpruio to control a
5 4-wire stepper motor:
6 
7 - configure 4 pins as output
8 - receive user action in loop
9 - inform user about the current state
10 - change motor direction
11 - change motor speed
12 - stop holded or in power off mode
13 - move a single step (in holded mode)
14 - quit
15 
16 Licence: GPLv3
17 
18 Copyright 2014 by Thomas{ dOt ]Freiherr[ At ]gmx[ DoT }net
19 
20 
21 Compile by:
22 
23 gcc -Wall -o stepper stepper.c /usr/local/lib/freebasic/fbrt0.o -lpruio -L"/usr/local/lib/freebasic/" -lfb -lpthread -lprussdrv -ltermcap -lsupc++ -Wno-unused-variable
24 
25 */
26 
27 
28 #define _GNU_SOURCE 1
29 #include "stdio.h"
30 #include <termios.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include "../c_wrapper/pruio_c_wrapper.h"
36 #include "../c_wrapper/pruio_pins.h"
37 
38 // output pins for the motor driver
39 #define P1 P8_08
40 #define P2 P8_10
41 #define P3 P8_12
42 #define P4 P8_14
43 
44 
45 /*! \brief wait for keystroke or timeout
46 \param mseconds timeout value in milliseconds
47 \returns 0 if timeout, 1 if input available, -1 if error
48 
49 Wait for a keystroke or timeout and return which of the events happened.
50 
51 */
52 int
53 isleep(unsigned int mseconds)
54 {
55  fd_set set;
56  struct timeval timeout;
57 
58  /* Initialize the file descriptor set. */
59  FD_ZERO(&set);
60  FD_SET(STDIN_FILENO, &set);
61 
62  /* Initialize the timeout data structure. */
63  timeout.tv_sec = 0;
64  timeout.tv_usec = mseconds * 1000;
65 
66  return TEMP_FAILURE_RETRY(select(FD_SETSIZE,
67  &set, NULL, NULL,
68  &timeout));
69 }
70 
71 /*! \brief make the motor move the next step.
72 \param Io pointer to PruIo structure
73 \param Rot direction of rotation (1 or -1)
74 
75 This function sets 4 output pins for a stepper motor driver. It
76 remembers the last step as static variable (starting at 0 = zero) and
77 adds the new position to it. So the Rot parameter should either be 1 or
78 -1 to make the motor move one step in any direction.
79 
80 */
81 void
82 move(PruIo *Io, char Rot) {
83  static int p = 0;
84 
85  p += Rot;
86  p &= 7; // &b111
87 
88  switch (p){
89  case 1:
90  pruio_gpio_out(Io, P1, 1); pruio_gpio_out(Io, P2, 0); pruio_gpio_out(Io, P3, 0); pruio_gpio_out(Io, P4, 0); break;
91  case 2:
92  pruio_gpio_out(Io, P1, 1); pruio_gpio_out(Io, P2, 1); pruio_gpio_out(Io, P3, 0); pruio_gpio_out(Io, P4, 0); break;
93  case 3:
94  pruio_gpio_out(Io, P1, 0); pruio_gpio_out(Io, P2, 1); pruio_gpio_out(Io, P3, 0); pruio_gpio_out(Io, P4, 0); break;
95  case 4:
96  pruio_gpio_out(Io, P1, 0); pruio_gpio_out(Io, P2, 1); pruio_gpio_out(Io, P3, 1); pruio_gpio_out(Io, P4, 0); break;
97  case 5:
98  pruio_gpio_out(Io, P1, 0); pruio_gpio_out(Io, P2, 0); pruio_gpio_out(Io, P3, 1); pruio_gpio_out(Io, P4, 0); break;
99  case 6:
100  pruio_gpio_out(Io, P1, 0); pruio_gpio_out(Io, P2, 0); pruio_gpio_out(Io, P3, 1); pruio_gpio_out(Io, P4, 1); break;
101  case 7:
102  pruio_gpio_out(Io, P1, 0); pruio_gpio_out(Io, P2, 0); pruio_gpio_out(Io, P3, 0); pruio_gpio_out(Io, P4, 1); break;
103  default:
104  pruio_gpio_out(Io, P1, 1); pruio_gpio_out(Io, P2, 0); pruio_gpio_out(Io, P3, 0); pruio_gpio_out(Io, P4, 1);
105  }
106 }
107 
108 
109 int main(int argc, char **argv)
110 {
111  PruIo *io = pruio_new(0, 0x98, 0, 1); /* create new driver structure */
112  do {
113  if (io->Errr) {
114  printf("initialisation failed (%s)\n", io->Errr); break;}
115 
117  printf("failed setting P1 (%s)\n", io->Errr); break;}
119  printf("failed setting P2 (%s)\n", io->Errr); break;}
121  printf("failed setting P3 (%s)\n", io->Errr); break;}
123  printf("failed setting P4 (%s)\n", io->Errr); break;}
124 
125  //' pin config OK, transfer local settings to PRU and start PRU driver
126  if (pruio_config(io, 0, 0x1FE, 0, 4, 0)) {
127  printf("config failed (%s)\n", io->Errr); break;}
128 
129  //' print user informations
130  printf("Controls: (other keys quit, 1 and 3 only when Direction = 0)\n");
131  printf(" 8 = faster\n");
132  printf(" 4 = rotate CW 5 = stop, hold position 6 = rotate CCW\n");
133  printf(" 1 = single step CW 2 = slower 3 = single step CCW\n");
134  printf(" 0 = stop, power off\n\n");
135  printf("Direction\tSleep\n");
136 
137  struct termios oldt, newt; // make terminal non-blocking
138  tcgetattr( STDIN_FILENO, &oldt );
139  newt = oldt;
140  newt.c_lflag &= ~( ICANON );
141  newt.c_cc[VMIN] = 0;
142  newt.c_cc[VTIME] = 1;
143  tcsetattr( STDIN_FILENO, TCSANOW, &newt );
144 
145  int w = 128, d = 0;
146  printf("%2d\t\t%3d", d, w); // user information
147  fflush(STDIN_FILENO);
148  while(1) { // run endless loop
149  if (d) move(io, d); // move the motor
150  if (1 == isleep(w)) {
151  switch (getchar()) { // evaluate keystroke
152  case '2': if (w < 512) w <<= 1; break;
153  case '8': if (w > 1) w >>= 1; break;
154  case '4': d = 1; break;
155  case '7': d = 2; break;
156  case '9': d = -2; break;
157  case '6': d = -1; break;
158  case '0': d = 0; pruio_gpio_out(io, P1, 0); pruio_gpio_out(io, P2, 0); pruio_gpio_out(io, P3, 0); pruio_gpio_out(io, P4, 0); break;
159  case '5': d = 0; move(io, d); break;
160  case '1': if (d == 0) move(io, 1); break;
161  case '3': if (d == 0) move(io, -1); break;
162  default: goto finish;
163  };
164  printf("\r%2d\t\t%3d", d, w); // user information
165  fflush(STDIN_FILENO);
166  }
167  }
168 
169 finish:
170  tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); // reset terminal
171 
172  // switch off pins
173  pruio_gpio_out(io, P1, 0); pruio_gpio_out(io, P2, 0); pruio_gpio_out(io, P3, 0); pruio_gpio_out(io, P4, 0);
174  // reset pin configurations
179 
180  printf("\n");
181  } while (0);
182 
183  pruio_destroy(io); /* destroy driver structure */
184  return 0;
185 }