Model Train control - Modify code to use MX1508 instead of L298N Motor Driver

Hi there,

i am trying to modify the code for my arduino nano from arduino railwaycontrol to use a different motor driver as the original one is too big.

The code is to control a model train via a bluetooth connected app. Very simple forward, backward, stop and a slider for the speed.

Original it uses the L298N and now i ordered a MX1508 "mini L298N". As i am still waiting for the driver to arrive, i had a look at the code and saw that they both work differentely as the MX1508 does not have a ENA Input. So the code needs to be changed but can not really find much about the MX1508 code on the web, especially with speed control.

The original code:

//--------------------------------------//
//   # WWW.ARDUINORAILWAYCONTROL.COM    //
//                                      //
//   ARDUINO GARDEN APP | FIRST SKETCH  //
//                                      //
//   V.1.2019  Steve Massikker          //
//--------------------------------------//

#include <SoftwareSerial.h>

// SOFTWARE SERIAL
SoftwareSerial Bluetooth(12, 13); // RX, TX

// L298
#define L298_ENA 9
#define L298_IN1 10
#define L298_IN2 11

// VARIABLES //
bool stringComplete = false;
String inputString = ""; 
//                     1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20
byte speedArray [] = {40, 50, 60, 70, 80, 90,100,110,120,130,140,150,160,170,180,190,200,220,240,255};
byte speedTrain = 0;

void setup() {

// Initializing Serial
  Bluetooth.begin(9600);
  Serial.begin(9600);  
  inputString.reserve(4); 

// Initializing Motor-Driver
  pinMode(L298_ENA, OUTPUT); 
  pinMode(L298_IN1, OUTPUT); 
  pinMode(L298_IN2, OUTPUT);

}

void loop() {

// ---- START PARSING INCOMING APP COMMANDS
  if (stringComplete) {

    if (inputString.charAt(0) =='a') {

      // Speed 
      if (inputString.charAt(1) =='0') {
        if (inputString.charAt(2) =='0') speedTrain = 0;
        if (inputString.charAt(2) =='1') speedTrain = speedArray[0];
        if (inputString.charAt(2) =='2') speedTrain = speedArray[1];
        if (inputString.charAt(2) =='3') speedTrain = speedArray[2];
        if (inputString.charAt(2) =='4') speedTrain = speedArray[3];
        if (inputString.charAt(2) =='5') speedTrain = speedArray[4];
        if (inputString.charAt(2) =='6') speedTrain = speedArray[5];
        if (inputString.charAt(2) =='7') speedTrain = speedArray[6];
        if (inputString.charAt(2) =='8') speedTrain = speedArray[7];
        if (inputString.charAt(2) =='9') speedTrain = speedArray[8]; 
      } 
      if (inputString.charAt(1) =='1') {
        if (inputString.charAt(2) =='0') speedTrain = speedArray[9];
        if (inputString.charAt(2) =='1') speedTrain = speedArray[10];
        if (inputString.charAt(2) =='2') speedTrain = speedArray[11];
        if (inputString.charAt(2) =='3') speedTrain = speedArray[12];
        if (inputString.charAt(2) =='4') speedTrain = speedArray[13];
        if (inputString.charAt(2) =='5') speedTrain = speedArray[14];
        if (inputString.charAt(2) =='6') speedTrain = speedArray[15];
        if (inputString.charAt(2) =='7') speedTrain = speedArray[16];
        if (inputString.charAt(2) =='8') speedTrain = speedArray[17];
        if (inputString.charAt(2) =='9') speedTrain = speedArray[18]; 
      }
      if (inputString.charAt(1) =='2') {      
        if (inputString.charAt(2) =='0') speedTrain = speedArray[19];
      }  

      // Direction and Stop
      if (inputString.charAt(1) =='d') {
        if (inputString.charAt(2) =='f') { // (f) Forward
          digitalWrite(L298_IN1, HIGH);
          digitalWrite(L298_IN2, LOW);
        }
        if (inputString.charAt(2) =='b') { // (b) Backward
          digitalWrite(L298_IN1, LOW);
          digitalWrite(L298_IN2, HIGH);
        }
        if (inputString.charAt(2) =='s') { // (s) Stop button
          digitalWrite(L298_IN1, LOW);
          digitalWrite(L298_IN2, LOW);
          speedTrain = 0;
        } 
      }
      analogWrite(L298_ENA, speedTrain); // Throttle
    }
    
    Serial.println(inputString); 
    inputString = "";
    stringComplete = false;
  }

  bluetoothEvent();
}


//// FUNCTIONS ////

void bluetoothEvent() {
  if (Bluetooth.available()) {
    char inChar = (char)Bluetooth.read();
    inputString += inChar;
    if (inChar == 'z') {
      stringComplete = true;
    }
  }
}

And what i changed yet:

//--------------------------------------//
//   # WWW.ARDUINORAILWAYCONTROL.COM    //
//                                      //
//   ARDUINO GARDEN APP | FIRST SKETCH  //
//                                      //
//   V.1.2019  Steve Massikker          //
//--------------------------------------//

#include <SoftwareSerial.h>

// SOFTWARE SERIAL
SoftwareSerial Bluetooth(12, 13); // RX, TX

// L298
#define MX1508_IN1 10
#define MX1508_IN2 11

// VARIABLES //
bool stringComplete = false;
String inputString = "";
//                     1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20
byte speedArray [] = {40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 220, 240, 255};
byte speedTrain = 0;

void setup() {

  // Initializing Serial
  Bluetooth.begin(9600);
  Serial.begin(9600);
  inputString.reserve(4);

  // Initializing Motor-Driver
  pinMode(MX1508_IN1, OUTPUT);
  pinMode(MX1508_IN2, OUTPUT);

}

void loop() {

  // ---- START PARSING INCOMING APP COMMANDS
  if (stringComplete) {

    if (inputString.charAt(0) == 'a') {

      // Speed
      if (inputString.charAt(1) == '0') {
        if (inputString.charAt(2) == '0') speedTrain = 0;
        if (inputString.charAt(2) == '1') speedTrain = speedArray[0];
        if (inputString.charAt(2) == '2') speedTrain = speedArray[1];
        if (inputString.charAt(2) == '3') speedTrain = speedArray[2];
        if (inputString.charAt(2) == '4') speedTrain = speedArray[3];
        if (inputString.charAt(2) == '5') speedTrain = speedArray[4];
        if (inputString.charAt(2) == '6') speedTrain = speedArray[5];
        if (inputString.charAt(2) == '7') speedTrain = speedArray[6];
        if (inputString.charAt(2) == '8') speedTrain = speedArray[7];
        if (inputString.charAt(2) == '9') speedTrain = speedArray[8];
      }
      if (inputString.charAt(1) == '1') {
        if (inputString.charAt(2) == '0') speedTrain = speedArray[9];
        if (inputString.charAt(2) == '1') speedTrain = speedArray[10];
        if (inputString.charAt(2) == '2') speedTrain = speedArray[11];
        if (inputString.charAt(2) == '3') speedTrain = speedArray[12];
        if (inputString.charAt(2) == '4') speedTrain = speedArray[13];
        if (inputString.charAt(2) == '5') speedTrain = speedArray[14];
        if (inputString.charAt(2) == '6') speedTrain = speedArray[15];
        if (inputString.charAt(2) == '7') speedTrain = speedArray[16];
        if (inputString.charAt(2) == '8') speedTrain = speedArray[17];
        if (inputString.charAt(2) == '9') speedTrain = speedArray[18];
      }
      if (inputString.charAt(1) == '2') {
        if (inputString.charAt(2) == '0') speedTrain = speedArray[19];
      }

      // Direction and Stop
      if (inputString.charAt(1) == 'd') {
        if (inputString.charAt(2) == 'f') { // (f) Forward
          digitalWrite(MX1508_IN2, LOW);
          analogWrite(MX1508_IN1, speedTrain);
        }
        if (inputString.charAt(2) == 'b') { // (b) Backward
          digitalWrite(MX1508_IN1, LOW);
          analogWrite(MX1508_IN2, speedTrain);
        }
        if (inputString.charAt(2) == 's') { // (s) Stop button
          digitalWrite(MX1508_IN1, HIGH);
          digitalWrite(MX1508_IN2, HIGH);
        }
      }
    }

    Serial.println(inputString);
    inputString = "";
    stringComplete = false;
  }

  bluetoothEvent();
}


//// FUNCTIONS ////

void bluetoothEvent() {
  if (Bluetooth.available()) {
    char inChar = (char)Bluetooth.read();
    inputString += inChar;
    if (inChar == 'z') {
      stringComplete = true;
    }
  }
}

But i dont think that this can work, for my understanding now the motor would only spin when the button "f" for forward or "b" for backward is pressed on the app. I do not get how this can work without a seperate Input for the speed.

Can someone help me to modify the code or give me a hint how this could work?

Thanks a lot in advance

Cedric

Hi,
for your reference see this link:

https://www.arduino.cc/reference/en/libraries/mx1508/

The code is too big? It must have fitted the Nano's flash memory before, why did it's size increase?

The driver module is too big? Why does it no longer fit?

Did you remove some code for speed control from the original code that worked with the L298?

Can you please post the original code, that worked with the L298, and the schematic showing how the circuit (Nano, motor driver etc) was connected. Then post the new schematic showing how the MX1508 is connected.

It seems to me that your error may have been to change too many things at once, by changing both the motor driver and the remote control solution at the same time.

Ah ... I may just have got it. You now need to make room for the BT receiver module, so you are changing to a physically smaller motor driver in order for everything to fit inside the model. That's why you are changing 2 things at the same time?

How was remote control achieved in the original circuit?

Thanks for the fast responses. Yes exactly the L298n is too big not the code :blush: I posted The original working code with L298n first, then the modified one.

Here is the original schema, in the modified one I would just leave the ENA away and connect to IN1 and IN2 the same way as in the original schema.

In theory the ideas in your modified code should work depending on the following:

  1. I do not know if a pin muxes correctly when changing between digitalWrite and then directly to analogWrite and back. As a guess I think it should OK for the 328.

  2. From the truth table for the MX1508 switching both pins low puts the outputs in high-z. I do not know how the chip recovers from high-z to on. Maybe it will be better to switch both pins to high which puts both outputs low instead of high-z.

  3. For the logic, how about this (assuming we use HIGH for the off condition):

void loop() {
  static bool forward = true;
  . . . '

      // Direction and Stop
      if (inputString.charAt(1) == 'd') {
        if (inputString.charAt(2) == 'f') { // (f) Forward
          digitalWrite(MX1508_IN2, HIGH);
          forward = true;
        }
        if (inputString.charAt(2) == 'b') { // (b) Backward
          digitalWrite(MX1508_IN1, HIGH);
          forward = false;
        }
        if (inputString.charAt(2) =='s') { // (s) Stop button
          digitalWrite(MX1508_IN1, LOW);
          digitalWrite(MX1508_IN2, LOW);
          speedTrain = 0;
        } 
      }
      if ( forward )
        analogWrite(MX1508_IN1, speedTrain);
      else
        analogWrite(MX1508_IN2, speedTrain);
    }

Thanks a lot, that sounds like a great solution! The MX1508 should arrive today and then I will test it directly :blush:

After some re-evaluation I think due to having the PWM inverted, using HIGH to turn power off, the analogWrites need to be changed.
The following should do it:

void loop() {
  static bool forward = true;
  . . . '

      // Direction and Stop
      if (inputString.charAt(1) == 'd') {
        if (inputString.charAt(2) == 'f') { // (f) Forward
          digitalWrite(MX1508_IN2, HIGH);
          forward = true;
        }
        if (inputString.charAt(2) == 'b') { // (b) Backward
          digitalWrite(MX1508_IN1, HIGH);
          forward = false;
        }
        if (inputString.charAt(2) =='s') { // (s) Stop button
          digitalWrite(MX1508_IN1, LOW);
          digitalWrite(MX1508_IN2, LOW);
          speedTrain = 255;
        } 
      }
      if ( forward )
        analogWrite(MX1508_IN1, 255 - speedTrain);
      else
        analogWrite(MX1508_IN2, 255 - speedTrain);
    }

When you get the module try it and you could also check if using LOW as off works.

It is not necessary to switch between analogWrite and digitalWrite. analogWrite(pin, 255) is exactly the same as digitalWrite(pin,HIGH), and analogWrite(pin,0) is the same as digitalWrite(pin,LOW).

Be aware that the MX1508 isn't really a replacement for the L298. Especially with regard to the max. motor voltage. The max. motor voltage for the MX1508 is only 10V. That is considerably less then the max motor voltage for the L298 and less than the 12V in your schematic.

I fully realize that. We use the analogWrite to control the PWM duty cycle to match the selected speed. So, one pin is set using digitalWrite and the other is PWM pulsed using analogWrite. To switch direction the pin assignments change - hence switching function between digitalWrite and analogWrite.

That could certainly be a problem. I did not check the max limits for the MX1508. I do not know what drive voltage the OP uses. In N-Gauge it will be about 12V and HO more towards 18V. So yes, for those that driver may not be usable. I can only assume the OP checked that.

First thanks a lot for the Input!

I use 7.2V battery on 3d printed garden railway with these 3-12V DC Motors: LINK

So i think the MX1508 should work.

I soldered them together, flashed the code and tested. Bluetooth does connect but control does not work ;(

With the following code i got minimal ticking in the motor but no rotation when changing from backward to forward on the app:

With this code i got minimal ticking in the motor but no rotation when changing speed on the app

Does it make any sense to you?

What can be the problem here?

Thanks a lot and kind regards
Cedric

Difficult to say.

7.2V should be fine for the MX1508.

Do you have the setup on the bench? The only way you are going to debug things will be looking at the signals with a scope, if you have one, or to serial.print the status at various stages in the code, like in the "forward", "reverse" and "speed" code blocks etc. Also, if possible, check the pin levels with a multi-meter.

Hi,
Can you please post a circuit diagram of your project?
Please not a Fritzy image.

An image of a hand drawn circuit will be fine, include power supplies, component names and pin labels.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.