Hi all,
I have a modelrailway at home and it's running on a network of Arduino's. The tracks are powered via L298N modules. The corresponding Arduino is sending a PWM signal to the L298N modules.
To communicate between the different Arduino's I use a Max485 module.
I don't know if I have to describe the global picture with all the arduino's and modules. It will become to much and complicated.
So now my problem I have recently.
One of the MAX485 modules didn't work anymore. The question is how can it happpen ?
Here a fritzing schema for 1 of the arduino's
Hardware components
Arduino : Nano
MAX485: RS-485 TTL to RS485
L298N: Dual H Bridge Dc Stepper Motor Drive Controller Board Module L298N
The MAX485LN modules are connected to each other as it should be. The First and the last module has a resistor of 100ohm between the A and B ports.
I suppose that the following is happening.
When a train a a specific track is "blocked" or not driving, the resistance on that track becomes very high.
Due to the common ground between the 3 modules, the MAX485 is burned up.
First question : Can this happen ?
Second question: Can I isolate the MAX485 and the Nano from the L298N modules via a Optocoupler? Keep in mind that the pins connected to the ENA and ENB of the L298N ports are sending a PWM signal.
Here the code for this Nano
/*
Besturing van SMD module voor 4 sporen modelspoor deel "Links"
by Marc Baeten
*/
#include <EEPROM.h>
#include <elapsedMillis.h>
#include "RS485_protocol.h"
#include <SoftwareSerial.h>
#define interval 500 // voor print logging
// sturing SMD High Low
#define inH A1
#define inL A2
#define SSerialRX 7 //Serial Receive pin
#define SSerialTX 8 //Serial Transmit pin
const byte ENABLE_PIN = 4; // enable sending rs485
SoftwareSerial rs485 (SSerialRX, SSerialTX); // receive pin, transmit pin
elapsedMillis timerRS485;
elapsedMillis timer0;
const byte nmbrOfBV = 4; // 3 + 1
// Arrays per baanvak
elapsedMillis timerSpoor[nmbrOfBV];
byte bzBV[nmbrOfBV];
byte stBV[nmbrOfBV];
byte oldStBV[nmbrOfBV];
byte treinID[nmbrOfBV];
int startSpeed[nmbrOfBV];
int targetSpeed[nmbrOfBV];
int vertragingTrein[nmbrOfBV];
int versnellingTrein[nmbrOfBV];
float speedPWM[nmbrOfBV]; // effectieve speed van het banvak.
boolean debugBV[nmbrOfBV];
const byte PWMtoBV [nmbrOfBV] = {0, 16, 15, 14}; // Index 0 not used
const byte pwmPIN[nmbrOfBV] = {0, 11, 10, 9}; // pins on Arduino
byte teller;
byte deviceId; //Variable to store data read from EEPROM.
byte mesCounter = 0;
boolean newMessage = false;
// Manual input of info or debug
int inputStatus = 0;
int inputValue = 0;
int inputID = 0;
int inputFunctie = 0;
byte debugRS485 = 1; //0 = NoDebug, 1 = OnlyError, 2 = NoWarning, 3 = All
boolean debugBezet = false;
boolean debugMessage = false;
// Speed controal via PWM
const byte maxSpeed = 200;
const byte minSpeed = 75;
byte msg[25];
byte buf[26];
//===========================================================================
// callback routines RS485
void fWrite (const byte what)
{
rs485.write (what);
}
int fAvailable ()
{
return rs485.available ();
}
int fRead ()
{
return rs485.read ();
}
//===========================================================================
// the setup function runs once when you press reset or power the board
void setup() {
EEPROM.get(0, deviceId);
Serial.begin(19200);
Serial.println ("");
Serial.print(F("Begin, Id = "));
Serial.println(deviceId, HEX);
int i;
rs485.begin (19200);
pinMode (ENABLE_PIN, OUTPUT); // driver output enable
digitalWrite (ENABLE_PIN, LOW); // disable sending
// init PWM pins
for (i = 1; i < nmbrOfBV; i++) { // index 0 not used
pinMode(pwmPIN[i], OUTPUT);
digitalWrite(pwmPIN[i], 0);
startSpeed[i] = 0;
targetSpeed[i] = 0;
bzBV[i] = 0;
stBV[i] = 0;
oldStBV[i] = 0;
treinID[i] = 0;
debugBV[i] = false;
}
pinMode(inH, OUTPUT);
pinMode(inL, OUTPUT);
digitalWrite(inH, HIGH);
digitalWrite(inL, LOW);
emptyMsg(0);
for (i = 0; i < sizeof(buf); i++) {
buf[i] = 0;
}
Serial.println ("Einde setup ");
}
//===========================================================================
// the loop function runs over and over again forever
void loop() {
if (Serial.available()) {
int inChar = Serial.read();
manualSetup(inChar);
}
if (debugRS485 > 2) {
Serial.print ("Loop: ");
Serial.print (teller++);
Serial.print (" ID: ");
Serial.print (deviceId, HEX);
}
receiveMessage();
if (newMessage) {
if (debugMessage) {
Serial.print ("St16: ");
Serial.print (stBV[1]);
Serial.print (" St15: ");
Serial.print (stBV[2]);
Serial.print (" St14: ");
Serial.print (stBV[3]);
Serial.print (" St16: ");
Serial.print (startSpeed[1]);
Serial.print (" St15: ");
Serial.print (startSpeed[2]);
Serial.print (" St14: ");
Serial.print (startSpeed[3]);
Serial.print (" Targ16: ");
Serial.print (targetSpeed[1]);
Serial.print (" Targ15: ");
Serial.print (targetSpeed[2]);
Serial.print (" Targ14: ");
Serial.print (targetSpeed[3]);
Serial.print (" ID16: ");
Serial.print (treinID[1]);
Serial.print (" ID15: ");
Serial.print (treinID[2]);
Serial.print (" ID14: ");
Serial.println (treinID[3]);
}
newMessage = false;
// verwerken ontvangen data
}
for (int i = 1; i < nmbrOfBV; i++) {
if (stBV[i] == 0) {
bzBV[i] = false;
// speedPWM[i] = 0;
} else {
bzBV[i] = true;
}
PWMSturing(i, pwmPIN[i], vertragingTrein[i], versnellingTrein[i]);
oldStBV[i] = stBV[i];
}
if (debugRS485 > 2) {
Serial.println (" ");
}
// print logging
if (timer0 > interval) {
printBezetBV();
printDebugBV();
timer0 = 0;
}
}
//=============PWM STURING ==============================================
void PWMSturing(int i, int pin, int vertragingTrein, int versnellingTrein)
{
float start = startSpeed[i];
float target = targetSpeed[i];
float versnelling = 0;
if (start > target) {
versnelling = - vertragingTrein;
} else {
versnelling = versnellingTrein;
}
if (stBV[i] != 0) {
if (oldStBV[i] == 0) {
timerSpoor[i] = 0;
speedPWM[i] = start;
}
float tijd = (timerSpoor[i] / 1000.0);
speedPWM [i] = (start + (tijd * versnelling));
if (versnelling < 0) { // afremmen
if (speedPWM[i] < target) {
speedPWM[i] = target;
}
} else { // optrekken
if (speedPWM[i] > target) {
speedPWM[i] = target;
}
}
}
speedPWM[i] = mini(maxSpeed, speedPWM[i]);
speedPWM[i] = maxi(minSpeed, speedPWM[i]);
analogWrite(pin, int(speedPWM[i]));
}
//===============================================================================
void receiveMessage() {
int received = recvMsg (fAvailable, fRead, buf, sizeof (buf), 250);
if (received > 0) {
if (debugRS485 > 2) {
Serial.print (" rcv: ");
if (received < 10 ) {
Serial.print (" ");
}
Serial.print (received);
}
if (received != buf[3] + 4) {
if (debugRS485 > 0) {
Serial.print ("Afzender ");
Serial.print (buf[0], HEX);
Serial.println (" lengte bericht NOK.");
}
return;
}
if (buf [0] != 1) {
if (debugRS485 > 2) {
printBuf (buf, received);
Serial.print (" Afz ");
Serial.print (buf[0], HEX);
Serial.print (" is niet de master.");
}
return;
}
if (buf [1] != deviceId) {
if (debugRS485 > 2) {
printBuf (buf, received);
Serial.print (" Ontv ");
Serial.print (buf[1], HEX);
Serial.print (" is niet mijn ID");
}
return;
}
if (!(buf [2] == 2 || buf [2] == 8 )) {
if (debugRS485 > 0) {
printBuf (buf, received);
Serial.print (" Comm ") ;
Serial.print (buf[2], HEX);
Serial.print (" niet gekend");
}
return;
}
// digitalWrite (LED_PIN, HIGH);
if (buf [2] == 2) {
msg[0] = deviceId; // Sender
msg[1] = 1; // Receiver 1 (naar master)
msg[2] = 3; // Function : return status
msg[3] = 2; // Size Data
msg[4] = buf[4];
msg[5] = 1; // no reader connected, always true returned
sendarduino();
if (debugRS485 > 2) {
Serial.print (" status ");
printBuf (msg, msg[3] + 4);
}
return;
}
if (buf [2] == 8) {
newMessage = true;
intToStBV(int(buf[5]), 1, 2);
intToStBV(int(buf[6]), 3, 0);
startSpeed[1] = int(buf[7]);
startSpeed[2] = int(buf[8]);
startSpeed[3] = int(buf[9]);
targetSpeed[1] = int(buf[10]);
targetSpeed[2] = int(buf[11]);
targetSpeed[3] = int(buf[12]);
vertragingTrein[1] = int(buf[13]);
vertragingTrein[2] = int(buf[14]);
vertragingTrein[3] = int(buf[15]);
versnellingTrein[1] = int(buf[16]);
versnellingTrein[2] = int(buf[17]);
versnellingTrein[3] = int(buf[18]);
treinID[1] = int(buf[19]);
treinID[2] = int(buf[20]);
treinID[3] = int(buf[21]);
msg[0] = deviceId; // Sender
msg[1] = 1; // Receiver 1 (naar master)
msg[2] = 9; // Function : Send reply PWM data
msg[3] = 4; // Size Data
msg[4] = buf[4];
msg[5] = int(speedPWM[1]);
msg[6] = int(speedPWM[2]);
msg[7] = int(speedPWM[3]);
sendarduino();
if (debugRS485 > 1) {
Serial.println ("");
if (debugRS485 > 2) {
Serial.print ("Loop: ");
Serial.print (teller);
Serial.print (" ID: ");
Serial.print (deviceId, HEX);
Serial.print (" snd: ");
}
Serial.print (msg[3] + 4);
printBuf (msg, msg[3] + 4);
}
if (debugRS485 == 2) {
Serial.println (" ");
}
return;
} // end send
} // end if something received
else {
if (debugRS485 > 0) {
if (received == -1) {
Serial.print (" Bad character ");
}
if (received == -2) {
Serial.print (" Bad crc ");
}
if (received == -3) {
Serial.print (" Overflow ");
}
}
if (debugRS485 > 1) {
if (received == 0) {
Serial.print (" Nothing received");
}
}
if (debugRS485 == 2) {
Serial.println (" ");
}
return;
}
}
//===========================================================================
void sendarduino () {
digitalWrite (ENABLE_PIN, HIGH); // enable sending
delay(2);
sendMsg (fWrite, msg, msg[3] + 4);
digitalWrite (ENABLE_PIN, LOW); // disable sending
// send message
if (debugRS485 > 1) {
//Serial.print (" Sent:");
printBuf(msg, msg[3] + 4);
}
}
//===========================================================================
void emptyMsg (int start) {
for (int i = start; i < sizeof(msg); i++) {
msg[i] = 0;
}
}
//===========================================================================
void intToStBV(int b, int i, int j)
{
stBV[i] = ((unsigned int)b >> 0) & 0x0F;
stBV[j] = ((unsigned int)b >> 4) & 0x0F;
}
//=============================================================================
float mini(float a, float b) {
if (a < b) {
return a;
} else {
return b;
}
}
//=============================================================================
float maxi(float a, float b) {
if (a > b) {
return a;
} else {
return b;
}
}
//===========================================================================
int getIndexBV(byte a) {
for (int i = 1; i < nmbrOfBV; i++)
{
if (PWMtoBV[i] == a) {
return i;
}
}
return 0;
}
//===========================================================================
void manualSetup(int inChar) {
Serial.print (" Ingelezen: ");
Serial.print ((char)inChar);
Serial.print (" int: ");
Serial.println (int(inChar));
if (isDigit(inChar)) {
if (inputStatus == 1 || inputStatus == 2) {
inputValue = inputValue * 10 + (inChar - 48);
return;
}
}
else {
if (int(inChar) == 61) { // =
inputID = inputValue;
inputStatus = 2;
inputValue = 0;
return;
}
if (int(inChar) == 65) { // A
inputFunctie = 5; // Debug Bezet
inputStatus = 1;
inputValue = 0;
return;
}
if (int(inChar) == 66) { // B
inputFunctie = 1; // Debug Baanvak
inputStatus = 1;
inputValue = 0;
return;
}
if (int(inChar) == 77) { // M
inputFunctie = 4; // Debug RS485
inputStatus = 1;
inputValue = 0;
return;
}
}
if (inChar == '\n') {
if (inputStatus == 2) {
if (inputFunctie == 1) { // Debug Baanvak
int i = getIndexBV(byte(inputID));
if (inputValue == 1) {
debugBV[i] = true;
} else {
debugBV[i] = false;
}
Serial.print ("Debug Baanvak: ");
Serial.print (inputID);
Serial.print (" value: ");
Serial.println (inputValue);
inputStatus = 0;
return;
}
if (inputFunctie == 4) { // Debug RS485
debugRS485 = inputValue;
Serial.print ("Debug RS485: ");
Serial.print (inputID);
Serial.print (" value: ");
Serial.println (inputValue);
inputStatus = 0;
return;
}
if (inputFunctie == 5) { // Debug bezet
debugBezet = inputValue;
Serial.print ("Debug Bezet: ");
Serial.print (inputID);
Serial.print (" value: ");
Serial.println (inputValue);
inputStatus = 0;
return;
}
}
}
}
//===========================================================================
void printBuf(byte * buffer, int bufferSize) {
for (int i = 0; i < bufferSize; i++) {
Serial.print (" ");
if (buffer[i] < 0x10) {
Serial.print ("0");
}
Serial.print (buffer[i], HEX);
}
Serial.print (" ");
}
//==============================================================================
void printBezetBV() {
if (debugBezet) {
int a = 0;
for (int i = 1 ; i < nmbrOfBV ; i++) {
if (bzBV[i]) {
printBV(i, 0);
a++;
}
}
if (a > 1) {
Serial.println ("-------------------------------------");
}
}
}
//==============================================================================
void printDebugBV() {
int a = 0;
for (int i = 1 ; i < nmbrOfBV ; i++) {
if (debugBV[i]) {
printBV(i, 0);
a++;
}
}
if (a > 1) {
Serial.println ("-------------------------------------");
}
}
//===========================================================================
void printBV(int i, int a) {
Serial.print (a);
Serial.print (" BV: ");
if (pwmPIN[i] == 0) {
Serial.print (">");
} else {
Serial.print ("<");
}
printInteger (PWMtoBV[i], 2);
Serial.print (" bz: ");
Serial.print (bzBV[i]);
Serial.print (" st: ");
Serial.print (stBV[i]);
Serial.print (" ID ");
printInteger (treinID[i], 2);
Serial.print (" start ");
printInteger (startSpeed[i], 3);
Serial.print (" sp: ");
printInteger (speedPWM[i], 3);
Serial.print (" targ ");
printInteger (targetSpeed[i], 3);
Serial.print (" timer: ");
printInteger (timerSpoor[i], 5);
Serial.println (" ");
}
//===========================================================================
void printInteger(unsigned long i, int n) {
if (n >= 5 && i < 10000) {
Serial.print("0");
}
if (n >= 4 && i < 1000) {
Serial.print("0");
}
if (n >= 3 && i < 100) {
Serial.print("0");
}
if (n >= 2 && i < 10) {
Serial.print("0");
}
Serial.print(i);
}
Thanks for any help




