[Resolved] Erratic operation when motor is supposed to be "asleep"

Hello,
I am hacking apart a slot car track as part of a project to make it controlled by an Arduino Uno. The premise is as follows: two players are prompted for simple math questions, and if they answer them correctly, their respective car goes faster. Currently, I am testing my track driver circuit (PWM pins 5 and 6 connected to TIP120 Darlingtons that then connect to the track) and it is all working beautifully except for one thing:
Sometimes, when the car's speed is at "zero," (PWM output is set to zero), one car (RED in the code, and the only one I am currently testing) moves erratically in tiny bursts, as if for some brief moment it is not actually set to zero. The interesting bit is that I am writing to my motors in an interrupt routine, and this behavior only happens when I set the period of the interrupt to happen at less than 10 milliseconds.

Here is my full code:

#include <TimerOne.h>

#define RedMotor 6
#define YellowMotor 5

#define MinSpeed 150
#define MaxSpeed 220
#define Off 0

#define LOOPDELAY 10

int RED = 0;	//Red and yellow PWM values
int YELLOW = 0; 

float motor = 0;
float step = 0.05;



void setup()
{

	Serial.begin(9600);
	pinMode(RedMotor, OUTPUT);
	pinMode(YellowMotor, OUTPUT);

	randomSeed(analogRead(3));//the only unused analog pin 

	Serial.println("Beginning Motor driver test.");

	analogWrite(RedMotor, Off);
	analogWrite(YellowMotor, Off);

	Timer1.setPeriod(200);//200 uS
	Timer1.attachInterrupt(WriteMotors);
}

void loop()
{
	int num1 = random(5);
	int num2 = random(5);
	int solution = num1 + num2;

	Serial.print(num1);Serial.print(" + "); Serial.print(num2);Serial.print(" =?   ");

	while(Serial.available() <=0)//This loop (decay loop for the speed) needs some delay to function correctly. 
	{
		motor -= step;
		RED = (int)motor;
		delay(LOOPDELAY);
	}
	int guess = Serial.parseInt();
	Serial.println(guess);
	if(guess == solution)//check the solution. If it is correct, speed up the car. 
	{
		motor += 40.00;
		Serial.println("Correct! :) ");
		
	}
	else
	{
		Serial.println("Incorrect! :(");
	}
	
	//constrain the motor values to (MinSpeed <= motor <= MaxSpeed)
	if(motor < (float)MinSpeed)
		motor = MinSpeed - 1.0;//set it to just under the minimum speed so the car stops, but close enough so a correct answer gets it moving again

	if(motor > (float)MaxSpeed)
		motor = MaxSpeed;
	
	Serial.print("Speed = ");Serial.println(motor);
}

void WriteMotors()
{
	if(RED > MinSpeed)
		RED = constrain(RED, MinSpeed, MaxSpeed);
	else if(RED < MinSpeed)
		RED = Off;

	if(YELLOW > MinSpeed)
		YELLOW = constrain(YELLOW, MinSpeed, MaxSpeed);
	else if(YELLOW < MinSpeed)
		YELLOW = Off;

	analogWrite(RedMotor, RED);
	analogWrite(YellowMotor, YELLOW);
}

I appreciate any and all feedback and help. Thank you!

All the variables you use to communicate with an interrupt routine must be declared "volatile".

Also you need to turn off interrupts whenever you change these variables from loop(), since
they are int, they are 2 bytes, and the ATmega is an 8 bit machine, so when you change
a 16 bit int you are doing two memory accesses, and the interrupt routine could run inbetween
the write to each byte.

volatile int RED = 0 ;
...

...
  noInterrupts () ;
  RED = (int) motor ;  // ensure atomic update of RED.
  interrupts () ;
...

These are basic rules you always have to follow for using interrupts.

Thank you! That has worked perfectly.

Good :slight_smile: