24v23 Speed Control with Arduino Mega and LCD

Hi,

I am currently working on with a Pololu Simple Motor Controller 24v23, with an Arduino Mega. I am using these eventually with a 360 pulse per revolution rotary encoder so that I can controller the speed of a DC motor with feedback. I am planning on setting the required speed on a 20 x 4 LCD display with a 12 pulse encoder. It forms part of a larger project, but as my programming skills are basic at the moment, I thought I would start off with just the dc motor, controller, LCD screen and Arduino initially without the encoder feedback to try and improve my understanding.

I have set the motor and controller up, and have them working over the USB interface. I have also used the Pololu Arduino program provided “Simple Program” and this all works fine. I have used the “Simple Program” as the basis for my program which is below, it still needs to be cleaned up.

In essence what I am trying to do, is use a 12 pulse per revolution encoder to set the setMotorSpeed(i), where “i” is the counts from the encoder via the use of the LCD screen. When the two toggle switches are turned to the high position the “i” value is then fixed and the motor starts rotating. Up to this point the program works fine.

What I then want to be able to do is toggle one of the switches to the low position, whilst still having the motor rotating at the same RPM. Modify the speed on the motor with the encoder, then when the switch is toggled back to high, the motor speed then increases or decreases to the modified value. But in the current program when I toggle the switch to the low position, the motor stops and starts rotating again when the switch is moved back high with the modified speed. I have tried a number of permutations of this, but they all end with the same result.

I was just wondering what I am doing wrong, as I am struggling at the moment to change the speed without the motor stopping. I think it is something with the way I am defining setMotorSpeed(i) but I am not sure.

Any help would be appreciated

#include <LiquidCrystal.h>

#include <SoftwareSerial.h>
#define rxPin 3 // pin 3 connects to smcSerial TX (not used in this example)
#define txPin 13 // pin 13 connects to smcSerial RX
SoftwareSerial smcSerial = SoftwareSerial(rxPin, txPin);


void exitSafeStart()
{
  smcSerial.write(0x83);
}
// speed should be a number from -3200 to 3200
void setMotorSpeed(int speed)
{
  smcSerial.write(0x85); // motor forward command
  smcSerial.write(speed & 0x1F);
  smcSerial.write(speed >> 5);
}

unsigned long lastmillis = 0;
unsigned long currentTime;
unsigned long loopTime;

const int pin_C = 6;   
const int pin_D = 7;  

unsigned char encoder_C;
unsigned char encoder_D;
unsigned char encoder_C_prev=0;
unsigned char encodercounter1;

int DatumToggle=51;  // datum toggle switch

int StartButton = 53;    //on/off toggle switch



LiquidCrystal lcd(26, 24, 29, 27, 25, 23);
int i=0;
int Counter=0;
int offset=0;



void setup()
{
  smcSerial.begin(19200);
  delay(5);
  smcSerial.write(0xAA); // send baud-indicator byte
  exitSafeStart(); // clear the safe-start violation and let the motor run
  delay(100);

  pinMode(DatumToggle, INPUT);
  pinMode(StartButton, INPUT);

  pinMode(pin_C, INPUT);
  pinMode(pin_D, INPUT);
  lcd.begin(20,4);
}

void loop()
{

  int DatumToggleState =digitalRead(DatumToggle);  // Datum Toggle Switch
  int StartButtonState =digitalRead(StartButton);  // ON/OFF  Toggle Switch


// Set the speed of the motor with the 12 ppr encoder

  if ((DatumToggleState == LOW)&&(Counter==0)){
    currentTime = millis();
    if(currentTime >= (loopTime + 5)){                // 5ms since last check of encoder = 200Hz  4ms = 250Hz  3ms = 333.33 Hz  2ms = 500 Hz

      encoder_C = digitalRead(pin_C);                 // Read encoder pins
      encoder_D = digitalRead(pin_D);   

      if((!encoder_C) && (encoder_C_prev)){           // C has gone from high to low 

        if(encoder_D) {                               // D is high so clockwise
          encodercounter1+=1;  
        }

        else {                                        // D is low so counter-clockwise   
          encodercounter1-=1;   // decrease the number, dont go below 0            
        }   
      } 
      encoder_C_prev = encoder_C;     // Store value of C for next time    
      loopTime = currentTime;  // Updates loopTime
    }
    offset = encodercounter1*50;
    lcd.setCursor(0,1);
    lcd.print(offset);
  }

// I think the problem is within the following part of the program but I not sure how to correct it.


//Set both switches to high and motor starts

  if ((DatumToggleState == HIGH)&&(StartButtonState==HIGH)&&(Counter>=0)){
    Counter=1;
    i=offset;
      setMotorSpeed(i); // full-speed forward

  }
  
// set DatumToggle low to modify speed with motor still running at the moment is stops

  if ((DatumToggleState == LOW)&&(StartButtonState==HIGH)&&(Counter==1)){
    Counter=0;
    i=i;
      setMotorSpeed(i); // i-speed forward

  }
  
  //Turn the start Button off to stop motor for good

  if ((StartButtonState==LOW)&&(Counter==1)&&(DatumToggleState==HIGH));
  {
    
    i=0;
          setMotorSpeed(i); // i-speed forward

  }
}

Hello.

I looked at your code briefly and noticed loopTime is not initialized at the start of your program, which could cause nondeterministic problems within your code. Also, there is no maximum and minimum values for encodercounter1, which could likely cause an overflow in the INT variable, especially if you are running your motor in one direction for a lengthy period of time. However, I am not sure if that is causing the issue. You might try debugging your code by using the Serial.println() command to verify that the correct conditional statement is executed based on the state of your switches and Counter variable and to see if the speed value i changes reasonably. Since it seems that you are mainly having Arduino programming issues, which are not related specifically to the Simple Motor Controller, you might also consider posting your problem on the Arduino Forum, as it has a much larger community and focus specifically on Arduinos.

By the way, it would be much more efficient to use interrupts to count the number of pulses of the encoder. You could use pin-change interrupts, which are supported on the Arduino Mega but not on all pins. You can find a list of external interrupt pins in the “Input and Output” section on the Arduino Mega page on the Arduino website.

- Amanda