Saturday, April 28, 2012

Arduino Controlled Motor

The more powerful simple generator which I had built always seemed like it should work as a perfectly respectable motor if I could just reverse the direction of the current with accurate enough control. The Arduino is perfect for this. I can turn on and off electricity with millisecond level control.

If the motor required less current than the Arduino itself could run the motor. Unfortunately the microcontroller is restricted to very low currents before components will melt. This can be worked around by using the Arduino to control relays.

A relay is simply a switch. Think of it as a light switch which can be turned on and off with an electronic signal. In this case I used some opto-isolated relays to control the output from a 13.5V wall wart (if you choose to repeat this, you can cut off the end connector of a wall wart and separate the wires; be careful though this can be a fire hazard if you leave it plugged in and don't pay attention to it; also make sure the amperage rating is high enough for the application).

I connected four relays to the arduino board. Two relays are connected to the positive lead from the wall wart, two to ground. I connected one relay attached to positive and one connected to ground to each wire coming from the generator. Then I turned the relays on and off such that the current would flow in opposite directions to ground. In the image below this means closing the relays connected to the brown wires than waiting a short time than closing the relays connected to the purple wires.

This is unlikely to be a workable solution for long term use. The relay will eventually burn up because it is just not rated for enough switching operations to run a motor for a useful length of time. I bought a MOSFET board to try and make a more useful solution but it mysteriously stopped working within an hour of my using it. 

In the video below it is running at about 600RPM. It runs a bit more trouble-free when at about half this speed.

Here is the code for it. It creates a basic inverter waveform where the voltage is high for 120 degrees, zero for 60 degrees, low for 120 degrees, than zero for another 60 degrees:

// constants won't change. Used here to
// set pin numbers:
const int PhaseA1 =  2;     // the number of a the pin used to control relay "A1"
const int PhaseA2 =  4;     // the number of a the pin used to control relay "A2"
const int PhaseB1 =  3;     // the number of a the pin used to control relay "B1"
const int PhaseB2 =  5;     // the number of a the pin used to control relay "A2"

// Variables will change:
int relayStateA1 = HIGH;             // relayState used to set the relay, HIGH is open
int relayStateA2 = LOW;
int relayStateB1 = LOW;
int relayStateB2 = HIGH;

long previousMillis = 0;        // will store last time since the cycle started

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long wavelength = 100;           // length of one full wavelength (milliseconds)

void setup() {
  // set the digital pins as output:
  pinMode(PhaseA1, OUTPUT);
  pinMode(PhaseA2, OUTPUT);
  pinMode(PhaseB1, OUTPUT);
  pinMode(PhaseB2, OUTPUT);


void loop()
unsigned long currentMillis = millis();

if(currentMillis - previousMillis < wavelength/2-wavelength/12 && currentMillis - previousMillis > wavelength/12) {
  relayStateA1=LOW;      // a LOW state will turn the relay on
  digitalWrite(PhaseA1, relayStateA1);    // turns "A1" relay on for 120 degrees of the cycle.
  digitalWrite(PhaseA2, relayStateA2);    // turns "A2" relay on for 120 degrees of the cycle
  digitalWrite(PhaseA1, relayStateA1);    // turns "A1" relay off for 240 degrees of a cycle
  digitalWrite(PhaseA2, relayStateA2);    // turns "A2" relay off for 240 degrees of a cycle
if(currentMillis - previousMillis > wavelength/2+wavelength/12 && currentMillis - previousMillis < 11*wavelength/12  ) {
  relayStateB1=LOW;      // Repeats what was done with A1 for B1
  digitalWrite(PhaseB1, relayStateB1);
  digitalWrite(PhaseB2, relayStateB2);
  relayStateB1=HIGH;  // Repeats what was done with A1 for B1
  digitalWrite(PhaseB1, relayStateB1);
  digitalWrite(PhaseB2, relayStateB2);


if(currentMillis - previousMillis > wavelength){
  previousMillis=currentMillis;    // Tells the program to start a new cycle


No comments: