Custom protocol

Hi ,
i've arduino Uno 3 and 4 shield relay , i create a code and it works nice on IDE BUT , i want SimHub trigger my code in custom protocol
i've create a formula ( same formula in my custom protocol ) for that

in Simhub debug window , i see Simhub send info , but my relay are still off like an error in void read

i'm too novice in coding and i don't understant why it's not work

if someone can help me... thanks

this is my void Read code :

post your full code with code tags, don't post image of code or don't post snippets (Snippets R Us!)

if you have not done so, please read How to get the best out of this forum and post accordingly.

More details about "SimHub trigger" would help also but possibly investigate the Firmata Library

1 Like

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum

Please post your full sketch, using code tags when you do

In my experience the easiest way to tidy up the code and add the code tags is as follows
Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

A bool is a single byte whose value will be either 0 for false or 1 for true, What value or values are you expecting in VariableABS, especially as you seem to be expecting a String rather than a single byte ?

1 Like

This is my full code

#ifndef SHCUSTOMPROTOCOL_H
#define SHCUSTOMPROTOCOL_H

#include <Arduino.h>

class SHCustomProtocol {
private:

public:

  /*
  CUSTOM PROTOCOL CLASS
  SEE https://github.com/zegreatclan/SimHub/wiki/Custom-Arduino-hardware-support

  GENERAL RULES :
    - ALWAYS BACKUP THIS FILE, reinstalling/updating SimHub would overwrite it with the default version.
    - Read data AS FAST AS POSSIBLE in the read function
    - NEVER block the arduino (using delay for instance)
    - Make sure the data read in "read()" function READS ALL THE DATA from the serial port matching the custom protocol definition
    - Idle function is called hundreds of times per second, never use it for slow code, arduino performances would fall
    - If you use library suspending interrupts make sure to use it only in the "read" function when ALL data has been read from the serial port.
      It is the only interrupt safe place

  COMMON FUNCTIONS :
    - FlowSerialReadStringUntil('\n')
      Read the incoming data up to the end (\n) won't be included
    - FlowSerialReadStringUntil(';')
      Read the incoming data up to the separator (😉 separator won't be included
    - FlowSerialDebugPrintLn(string)
      Send a debug message to simhub which will display in the log panel and log file (only use it when debugging, it would slow down arduino in run conditions)

  */

  // Called when starting the arduino (setup method in main sketch)

  // Called when new data is coming from computer
  

const int solenoid1Pin = 8;  // Relais pour solénoïde 1 sur la pin 8
const int solenoid2Pin = 12; // Relais pour solénoïde 2 sur la pin 12
const int motorPin = 7;      // Relais pour moteur sur la pin 7

const int solenoidFrequency = 10;    // Fréquence des solénoïdes en Hz
const int solenoidInterval = 1000 / (2 * solenoidFrequency);  // Intervalle pour la fréquence de 10 Hz (en millisecondes)

const int minActivationTime = 500;   // Temps minimum d'activation en millisecondes (0,5 sec)

unsigned long previousMillisSolenoid = 0;  // Stocke le dernier temps de changement pour les solénoïdes
unsigned long activationStartMillis = 0;   // Stocke le temps de début de l'activation
unsigned long previousMillisABS = 0;   // Stocke le temps de début de l'activation
unsigned long absToggleInterval = 2000;   // Stocke le temps de début de l'activation

bool solenoid1State = false;   // État actuel du solénoïde 1
bool solenoid2State = false;   // État actuel du solénoïde 2
bool VariableABS = false;      // Variable qui indique si l'ABS est actif ou non
bool absActive = false;        // Indique si les relais sont en train d'être activés
unsigned long currentMillis = millis();

void read() {
  
bool VariableABS = FlowSerialReadStringUntil('\n');
FlowSerialDebugPrintLn("SpeedProut : " + String(VariableABS));
  }


void setup() {
  pinMode(solenoid1Pin, OUTPUT);
  pinMode(solenoid2Pin, OUTPUT);
  pinMode(motorPin, OUTPUT);
  
  // Initialisation des relais à l'état bas (éteint)
  digitalWrite(solenoid1Pin, LOW);
  digitalWrite(solenoid2Pin, LOW);
  digitalWrite(motorPin, LOW);
}

void loop() {
 
  FlowSerialDebugPrintLn("SpeedProut2 : " + String(VariableABS));
  unsigned long currentMillis = millis();

// Gérer l'alternance de la variable VariableABS toutes les 2 secondes
 

    if (VariableABS) {
      // Si l'ABS devient actif, enregistrer le temps de début d'activation
      activationStartMillis = currentMillis;
      absActive = true;
    }
  
  // Détection de l'activation de l'ABS
  if (VariableABS && !absActive) {
    // Si l'ABS devient actif, enregistrer le temps de début d'activation
    activationStartMillis = currentMillis;
    absActive = true;
  }
  
  // Si VariableABS est 1 (ABS activé) ou si le temps minimum d'activation n'est pas écoulé
  if (VariableABS || (absActive && (currentMillis - activationStartMillis < minActivationTime))) {
    // Activer le moteur en continu
    digitalWrite(motorPin, HIGH);
    
    // Gérer l'alternance des solénoïdes à 10 Hz
    if (currentMillis - previousMillisSolenoid >= solenoidInterval) {
      previousMillisSolenoid = currentMillis;
      
      // Inverser l'état des solénoïdes
      solenoid1State = !solenoid1State;
      solenoid2State = !solenoid2State;
      
      digitalWrite(solenoid1Pin, solenoid1State ? HIGH : LOW);
      digitalWrite(solenoid2Pin, solenoid2State ? HIGH : LOW);
    }
  } else {
    // Si le temps minimum d'activation est écoulé, désactiver les relais
    digitalWrite(solenoid1Pin, LOW);
    digitalWrite(solenoid2Pin, LOW);
    digitalWrite(motorPin, LOW);
    
    // Réinitialiser les états
    solenoid1State = false;
    solenoid2State = false;
    absActive = false;  // Réinitialiser l'état d'activation
  }
}

    void idle() {
    
  };
};
#endif

SimHub send 0 or 1 ( or true of false )

when 1 use my code in Arduino IDE , all relay works fine

So i think there is a communication problem between rdu and SimHub

this is my Formula for Custom Protocol

What am I expected to see? As requested earlier do not use screen shots. Follow the advice of @J-M-L and @UKHeliBob.

i send my sketch just above , last screenshot is for Simhub formula that i put in my sketch

I would start with simply printing what you receive.

void setup
{
  Serial.begin(9600);
}

void loop()
{
  if(Serial.available())
  {
    byte b = Serial.read();
    if(b < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(b, HEX);
  }
}

This will print received bytes in hex. If you only see 0x00 or 0x01, simhub does not send a '\n'.

Notes:

  1. You seem to be missing a Serial.begin().
  2. You seem to be missing the FlowSerialDebugPrintLn function.
  3. Why are loop() and setup() part of your class?
  4. Does simhub send a '\n'?
  5. I'm not familiar with simhub. If simhub does not provide a monitor to see what is received, you can toggle the L-LED (if available on your board) based on the received value.

Does it send them as a byte, ie 0 or 1 or as a String, ie "0" or "1" ? They are not the same thing

I know

I Can choose if i'm using 0 or 1
Or
Raw data true or false in formula

In this sketch, i'm using 0 - 1

Ok , i'll try thanks

Update

Now , i know the communication is good but a new problem is here ..

But if i set int VariableABS = 1; it works fine ( just no trigger like i want to )

#ifndef SHCUSTOMPROTOCOL_H
#define SHCUSTOMPROTOCOL_H

#include <Arduino.h>

class SHCustomProtocol {
private:

public:

  /*
  CUSTOM PROTOCOL CLASS
  SEE https://github.com/zegreatclan/SimHub/wiki/Custom-Arduino-hardware-support

  GENERAL RULES :
    - ALWAYS BACKUP THIS FILE, reinstalling/updating SimHub would overwrite it with the default version.
    - Read data AS FAST AS POSSIBLE in the read function
    - NEVER block the arduino (using delay for instance)
    - Make sure the data read in "read()" function READS ALL THE DATA from the serial port matching the custom protocol definition
    - Idle function is called hundreds of times per second, never use it for slow code, arduino performances would fall
    - If you use library suspending interrupts make sure to use it only in the "read" function when ALL data has been read from the serial port.
      It is the only interrupt safe place

  COMMON FUNCTIONS :
    - FlowSerialReadStringUntil('\n')
      Read the incoming data up to the end (\n) won't be included
    - FlowSerialReadStringUntil(';')
      Read the incoming data up to the separator (😉 separator won't be included
    - FlowSerialDebugPrintLn(string)
      Send a debug message to simhub which will display in the log panel and log file (only use it when debugging, it would slow down arduino in run conditions)

  */
const int solenoid1Pin = 8;  // Relais pour solénoïde 1 sur la pin 8
const int solenoid2Pin = 12; // Relais pour solénoïde 2 sur la pin 12
const int motorPin = 7;      // Relais pour moteur sur la pin 7

const int solenoidFrequency = 10;    // Fréquence des solénoïdes en Hz
const int solenoidInterval = 1000 / (2 * solenoidFrequency);  // Intervalle pour la fréquence de 10 Hz (en millisecondes)

const int minActivationTime = 500;   // Temps minimum d'activation en millisecondes (0,5 sec)

unsigned long previousMillisSolenoid = 0;  // Stocke le dernier temps de changement pour les solénoïdes
unsigned long activationStartMillis = 0;   // Stocke le temps de début de l'activation
unsigned long previousMillisABS = 0;   // Stocke le temps de début de l'activation
unsigned long absToggleInterval = 1000;   // Stocke le temps de début de l'activation

int solenoid1State = 0;   // État actuel du solénoïde 1
int solenoid2State = 0;   // État actuel du solénoïde 2
int VariableABS = 0;      // Variable qui indique si l'ABS est actif ou non
int absActive = 0;        // Indique si les relais sont en train d'être activés
unsigned long currentMillis = millis();

  // Called when starting the arduino (setup method in main sketch)

void setup() {
  // put your setup code here
  pinMode(solenoid1Pin, OUTPUT);
  pinMode(solenoid2Pin, OUTPUT);
  pinMode(motorPin, OUTPUT);
  
  // Initialisation des relais à l'état bas (éteint)
  digitalWrite(solenoid1Pin, LOW);
  digitalWrite(solenoid2Pin, LOW);
  digitalWrite(motorPin, LOW);
}

  // Called when new data is coming from computer
  
void read() {
  
bool VariableABS =FlowSerialReadStringUntil('0').toInt();
FlowSerialDebugPrintLn("ABS : " + String(VariableABS) );
  }

void loop() {

  unsigned long currentMillis = millis();

// Gérer l'alternance de la variable VariableABS toutes les 2 secondes
 

    if (VariableABS) {
      // Si l'ABS devient actif, enregistrer le temps de début d'activation
      activationStartMillis = currentMillis;
      absActive = 1;
    }
  
  // Détection de l'activation de l'ABS
  if (VariableABS && !absActive) {
    // Si l'ABS devient actif, enregistrer le temps de début d'activation
    activationStartMillis = currentMillis;
    absActive = 1;
  }
  
  // Si VariableABS est 1 (ABS activé) ou si le temps minimum d'activation n'est pas écoulé
  if (VariableABS || (absActive && (currentMillis - activationStartMillis < minActivationTime))) {
    // Activer le moteur en continu
    digitalWrite(motorPin, HIGH);
    
    // Gérer l'alternance des solénoïdes à 10 Hz
    if (currentMillis - previousMillisSolenoid >= solenoidInterval) {
      previousMillisSolenoid = currentMillis;
      
      // Inverser l'état des solénoïdes
      solenoid1State = !solenoid1State;
      solenoid2State = !solenoid2State;
      
      digitalWrite(solenoid1Pin, solenoid1State ? HIGH : LOW);
      digitalWrite(solenoid2Pin, solenoid2State ? HIGH : LOW);
    }
  } else {
    // Si le temps minimum d'activation est écoulé, désactiver les relais
    digitalWrite(solenoid1Pin, LOW);
    digitalWrite(solenoid2Pin, LOW);
    digitalWrite(motorPin, LOW);
    
    // Réinitialiser les états
    solenoid1State = 0;
    solenoid2State = 0;
    absActive = 0;  // Réinitialiser l'état d'activation
  }
}

    void idle() {
    
  };
};
#endif

hi ,

i found my problem

double call ( in setup and read ) , i remove call in void read and it works fine

Thanks for trying to help me

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