Here is the code used in the first video showing the tethered locomotive moving back and forth. The analog speed input is disabled and instead a direction variable tells the motor to switch directions every few seconds.
// PWM Motor controller with direction control via // input potentiometer // // (C) 2014 zapmaker // // Apache 2.0 License // const int analogIn0Pin = 0; const int ledPin = 13; const int interruptNumber = 0;// usually connects to pin 2 const int pwmPin = 3; const int dir1Pin = 4; const int dir2Pin = 5; volatile int state = LOW; volatile int lastTime = 0; int last = 0; int motorTime = 0; int serialTime = 0; int delta = 0; int pwmOut = 0; int lastDir1 = 0; int lastDir2 = 0; float detectedSpeed = 0; boolean useBrakingOnReversal = false; int lastswaptime = 0; #define SVAL 390 int dirX = SVAL; #define SDELT 3000 #define BUFSIZE 200 char buf[BUFSIZE]; void setup() { Serial.begin(9600); // pinMode(ledPin, OUTPUT); attachInterrupt(interruptNumber, blink, RISING); digitalWrite(pwmPin, pwmOut); pinMode(pwmPin, OUTPUT); digitalWrite(dir1Pin, lastDir1); pinMode(dir1Pin, OUTPUT); digitalWrite(dir2Pin, lastDir2); pinMode(dir2Pin, OUTPUT); } void loop() { int curr = millis(); if (last != lastTime) { int tmp = lastTime - last; if (tmp > 30) { delta = tmp; } last = lastTime; } else if ((curr - lastTime) > 3000) { delta = 0; } if ((curr - motorTime) > 100) { //int a = analogRead(analogIn0Pin); int a = dirX; a /= 4; // split the potentiometer in half, incrementing // the speed in opposite motor direction from the // middle of the pot if (a <= 127) { // bottom half of pot if (lastDir1 == 0 && lastDir2 == 1) { // reversal occurred, stop motor to protect // motor and controller stop(); // ensure no pwm signal, just dc a = 255; } else { // change direction lastDir1 = 1; lastDir2 = 0; a = (127 - a) * 2; } } else { // top half of pot if (lastDir1 == 1 && lastDir2 == 0) { // reversal occurred, stop motor to protect // motor and controller stop(); // ensure no pwm signal, just dc a = 255; } else { // change direction lastDir1 = 0; lastDir2 = 1; a = (a - 128) * 2; } } // motor direction digitalWrite(dir1Pin, lastDir1); digitalWrite(dir2Pin, lastDir2); pwmOut = a; // pwm 'speed' analogWrite(pwmPin, pwmOut); float d = delta; detectedSpeed = 0; if (d > 0) detectedSpeed = 10000 / d; motorTime = curr; } if ((curr - lastswaptime) > SDELT) { if (dirX < 512) dirX = 512 + SVAL; else dirX = 512 - SVAL; lastswaptime = curr; } if ((curr - serialTime) > 1000) { String msg = "L1: "; msg += lastDir1; msg += " L2: "; msg += lastDir2; msg += " A: "; msg += pwmOut; msg += "\n"; msg.toCharArray(buf, BUFSIZE); Serial.write(buf); msg = "Pulse Time: "; msg += delta; msg += " Speed: "; msg += (int)detectedSpeed; msg += "\n"; msg.toCharArray(buf, BUFSIZE); Serial.write(buf); serialTime = curr; } digitalWrite(ledPin, state); } void stop() { // decide if we are braking on stop or // letting motor coast if (useBrakingOnReversal) { lastDir1 = 0; lastDir2 = 0; } else { lastDir1 = 1; lastDir2 = 1; } } void blink() { lastTime = millis(); state = !state; }