INDIO digital outputs
The Industruino INDIO has 8 digital outputs of the type: galvanically isolated high-side driver (Charge pump NFET). Each channel can deliver 2.6A at the supply voltage (typically 12 or 24V). Maximum switching frequency is 400Hz.
This allows us to drive a UNIPOLAR stepper motor directly from 4 pins (1-4 in the picture on the left), with the common wires connected to GND. The common wires cannot be connected to the supply voltage because the output pins, as high-side drivers, cannot sink any current. This is also why as far as i understand, it is impossible to drive a bipolar stepper motor with high-side drivers only. For reference see this excellent explanation on steppers.
Unipolar stepper motors have 5 or 6 wires. Below test was done with a 5-wire PM35S-048 stepper which has 48 steps per rotation and is rated for 24V, but we did the test with around 10V.
The maximum switching frequency of 400Hz would allow 400 steps per second in theory. For 48 steps per rotation, that means max 400/48=8.3 rotations per second, or 500 RPM. Indeed my test confirmed that the stepper works accurately up to 500 RPM; 600 RPM did not work.
This is the code used of the above example:
- a startup screen that allows to move the stepper using the up/down buttons
- press enter to start a standard routine: full 360 rotation clockwise, back anti-clockwise with stops at 240 and 120 degrees
- press enter to change the speed (rpm)
/* * test Industruino INDIO 1286 with stepper motor directly to 4 digital outputs * to work with UNIPOLAR stepper motor = 5 or 6 wires * 2 wires per coil * extra wire(s) to GND (Indio has hig side drivers, cannot sink current) * * see http://www.tigoe.net/pcomp/code/circuits/motors/stepper-motors/ * code based on the Arduino standard Stepper library, modified to work with Industruino INDIO digital channels * * Tom Tobback March 2017 */ #include <Indio.h> #include <Wire.h> #include <UC1701.h> static UC1701 lcd; // CONFIGURATION const int motor_pin_1 = 1; const int motor_pin_2 = 2; const int motor_pin_3 = 3; const int motor_pin_4 = 4; int motor_speed = 60; // the motor speed, in revolutions per minute int number_of_steps = 48; // total number of steps for this motor // INTERNAL int step_number = 0; // which step the motor is on unsigned long last_step_time = 0; // time stamp in us of the last step taken const int button_enter_pin = 24; const int button_up_pin = 25; const int button_down_pin = 23; //////////////////////////////////////////////////////////////////////////////// void setup() { lcd.begin(); lcd.setCursor(10, 1); lcd.print("Unipolar Stepper"); lcd.setCursor(50, 2); lcd.print("TEST"); lcd.setCursor(0, 4); lcd.print("press Up/Down for pos"); lcd.setCursor(0, 6); lcd.print("press Enter to start"); pinMode(26, OUTPUT); // LED digitalWrite(26, LOW); // LOW = backlight ON pinMode(button_enter_pin, INPUT); pinMode(button_up_pin, INPUT); pinMode(button_down_pin, INPUT); Indio.digitalMode(motor_pin_1, OUTPUT); Indio.digitalMode(motor_pin_2, OUTPUT); Indio.digitalMode(motor_pin_3, OUTPUT); Indio.digitalMode(motor_pin_4, OUTPUT); Indio.digitalWrite(motor_pin_1, LOW); Indio.digitalWrite(motor_pin_2, LOW); Indio.digitalWrite(motor_pin_3, LOW); Indio.digitalWrite(motor_pin_4, LOW); while (digitalRead(button_enter_pin)) { if (!digitalRead(button_up_pin)) step(1); if (!digitalRead(button_down_pin)) step(-1); } lcd.clear(); lcd.setCursor(10, 1); lcd.print("Unipolar Stepper"); lcd.setCursor(10, 4); lcd.print("Speed (rpm): "); lcd.setCursor(10, 6); lcd.print("hold Enter to"); lcd.setCursor(10, 7); lcd.print("change speed"); } //////////////////////////////////////////////////////////////////////////////// void loop() { lcd.setCursor(100, 4); lcd.print(motor_speed); lcd.print(" "); step(number_of_steps); delay(2000); changeSpeed(); step(-number_of_steps / 3); delay(1000); changeSpeed(); step(-number_of_steps / 3); delay(1000); changeSpeed(); step(-number_of_steps / 3); delay(1000); changeSpeed(); } //////////////////////////////////////////////////////////////////////////////// void step(int steps_to_move) { unsigned long step_delay = 60L * 1000L * 1000L / number_of_steps / motor_speed; int steps_left = abs(steps_to_move); // how many steps to take int direction; // motor direction // determine direction based on whether steps_to_mode is + or -: if (steps_to_move > 0) { direction = 1; } if (steps_to_move < 0) { direction = 0; } // decrement the number of steps, moving one step each time: while (steps_left > 0) { unsigned long now = micros(); // move only if the appropriate delay has passed: if (now - last_step_time >= step_delay) { // get the timeStamp of when you stepped: last_step_time = now; // increment or decrement the step number, // depending on direction: if (direction == 1) { step_number++; if (step_number == number_of_steps) { step_number = 0; } } else { if (step_number == 0) { step_number = number_of_steps; } step_number--; } // decrement the steps left: steps_left--; // step the motor to step number 0, 1, ..., {3 or 10} stepMotor(step_number % 4); } } } //////////////////////////////////////////////////////////////////////////////// void stepMotor(int thisStep) { switch (thisStep) { case 0: // 1010 Indio.digitalWrite(motor_pin_1, HIGH); Indio.digitalWrite(motor_pin_2, LOW); Indio.digitalWrite(motor_pin_3, HIGH); Indio.digitalWrite(motor_pin_4, LOW); break; case 1: // 0110 Indio.digitalWrite(motor_pin_1, LOW); Indio.digitalWrite(motor_pin_2, HIGH); Indio.digitalWrite(motor_pin_3, HIGH); Indio.digitalWrite(motor_pin_4, LOW); break; case 2: //0101 Indio.digitalWrite(motor_pin_1, LOW); Indio.digitalWrite(motor_pin_2, HIGH); Indio.digitalWrite(motor_pin_3, LOW); Indio.digitalWrite(motor_pin_4, HIGH); break; case 3: //1001 Indio.digitalWrite(motor_pin_1, HIGH); Indio.digitalWrite(motor_pin_2, LOW); Indio.digitalWrite(motor_pin_3, LOW); Indio.digitalWrite(motor_pin_4, HIGH); break; } } void changeSpeed() { if (!digitalRead(button_enter_pin)) { lcd.setCursor(10, 6); lcd.print("change speed "); lcd.setCursor(10, 7); lcd.print(" "); delay(2000); while (digitalRead(button_enter_pin)) { if (!digitalRead(button_up_pin)) motor_speed++; if (!digitalRead(button_down_pin)) motor_speed--; motor_speed = constrain(motor_speed, 0, 600); lcd.setCursor(100, 4); lcd.print(motor_speed); lcd.print(" "); delay(50); } lcd.setCursor(10, 6); lcd.print("hold Enter to "); lcd.setCursor(10, 7); lcd.print("change speed "); } }