0
votes

this concerns both Arduino and Node-red so I'm asking this here!

I am currently doing a project involving a Raspberry Pi 4, Arduino Mega and a few voltage/current sensors. The sensors will be connected to the Arduino via i2c, so the values from the sensors will be read by the Arduino. Besides just passively reading the analog inputs, the Arduino sketch I've made also includes logic control where relay switches will open/close based on the sensor readings.

With the Arduino sketch doing the actual thinking, I would like to use Node-Red on my Pi to act as a visualization tool. For example, my Node-Red dashboard would have a bunch of switches to control the operation of the relay switches, and gauges to display the sensor values in real-time.

I have read up on Firmata and StandardFirmata works well on its own, but how will I combine StandardFirmata with the Arduino sketch I already have?

Are there any other ways to get my theory to work?

Thanks!!

Here's my Arduino sketch if needed.

#include <Wire.h>

//using Arduino Mega 2560
//Virtual Node-red relay input IN1
const byte IN1 = 22; 
const byte IN2 = 24;
const byte IN3 = 26;
//Physical relay output K1
const byte K1 = 23; 
const byte K2 = 25;
const byte K3 = 27;
//Virtual Node-red switches
const byte Power = 28;   
const byte Charging = 30;
const byte Manual = 32;
const byte GetValues = 19;  //Interrupt Pin 19 on Mega2560

volatile int InterruptState = LOW;
//Sensor variables
float shuntvoltage_PV = 0;
float busvoltage_PV = 0;
float current_mA_PV = 0;
float loadvoltage_PV = 0;
float power_mW_PV = 0;

float shuntvoltage_Load = 0;
float busvoltage_Load = 0;
float current_mA_Load = 0;
float loadvoltage_Load = 0;
float power_mW_Load = 0;

int current_mA_Batt = 0;  

void setup()
{
  pinMode( IN1, INPUT );
  pinMode( IN2, INPUT );
  pinMode( IN3, INPUT );
  pinMode( K1, OUTPUT );
  pinMode( K2, OUTPUT );
  pinMode( K3, OUTPUT );
  pinMode( Power, INPUT );
  pinMode( Charging, INPUT );
  pinMode( Manual, INPUT );
  pinMode( GetValues, INPUT );

  attachInterrupt( digitalPinToInterrupt( GetValues ), ISR_GetValues, RISING );

  Serial.begin(9600);
}//setup

void loop()
{
  const int ST_POWER = 40;
  const int ST_CHARGING = 41;
  const int ST_MANUAL = 42;
  const int ST_CHECK_CURRS = 43;
  static byte stateControl = ST_POWER;

  switch ( stateControl )
  {
    case  ST_POWER:
      //Power
      if ( digitalRead( Power ) == HIGH ) {
        stateControl = ST_CHARGING;
      }
      break;

    case  ST_CHARGING:
      //Charging on?
      if ( digitalRead( Charging ) == LOW ) {
        //No
        stateControl = ST_MANUAL;
      }
      else {
        //Yes
        digitalWrite( K1, LOW );
        digitalWrite( K2, LOW );
        digitalWrite( K3, HIGH );
        stateControl = ST_CHARGING; //redundant, presented for illustrative purposes
      }//else
      break;

    case  ST_MANUAL:
      //Manual mode on?
      if ( digitalRead( Manual ) == LOW ) {
        //No
        stateControl = ST_CHECK_CURRS;
      }
      else {
        //Yes
        //Manual Operation of IN1, INT2, IN3
        //assumed to return false when "finished" manual operation
        //when done, go back to charging state
        if ( !HandleManualInputs() ) {
          stateControl = ST_CHARGING;
        }
      }//else
      break;

    case  ST_CHECK_CURRS:
      //Is Ipv > 0A?
      if ( current_mA_PV > 0.0 ) {
        //Yes
        digitalWrite( K2, HIGH );
        //Is Il = Ipv?
        if ( current_mA_Load == current_mA_PV ) {
          //Yes
          digitalWrite( K1, LOW );
          digitalWrite( K3, LOW );
        }//if
        //No
        //Is Il > Ipv?
        else if ( current_mA_Load > current_mA_PV ) {
          //Yes
          digitalWrite( K1, HIGH );
          digitalWrite( K3, LOW );
        }//else if
        //No
        //Is Il < Ipv?
        else {
          //Yes
          digitalWrite( K1, HIGH );
          digitalWrite( K3, LOW );
        }//else

      }//if
      //No
      //Is Il <= Ibatt?
      else if ( current_mA_Load <= current_mA_Batt ) {
        //Yes
        digitalWrite( K1, LOW );
        digitalWrite( K2, HIGH );
        digitalWrite( K3, HIGH );
      }//else if
      //No
      //Is Il > Ibatt?
      else {
        //Yes
        digitalWrite( K1, HIGH );
        digitalWrite( K2, LOW );
        digitalWrite( K3, LOW );
      }//else
      //No
      //Go back to chargin state
      stateControl = ST_CHARGING;
      break;
  }//switch
}//loop

bool HandleManualInputs( void )
{
  //"Manual Operation of IN1, IN2 and IN3"
  if ( digitalRead(Manual) == HIGH ) {
    digitalWrite( K1, LOW );
    digitalWrite( K2, LOW );
    digitalWrite( K3, LOW );
  }
}//HandleManualInputs

void ISR_GetValues( void )
{
  //"Get voltage/current of PV, Gen, Load and Batt"
  if (InterruptState = digitalRead(GetValues))
  {
    /*Serial.println("              INA219_PV  |   INA219_Load   ");
    Serial.print("Load Voltage:  "); Serial.print(loadvoltage_PV); Serial.print("      | "); Serial.print(loadvoltage_Load); Serial.println(" V");
    Serial.print("Current:       "); Serial.print(current_mA_PV); Serial.print("       | "); Serial.print(current_mA_Load); Serial.println("  mA");
    Serial.print("Power:         "); Serial.print(power_mW_PV); Serial.print("         | "); Serial.print(power_mW_Load); Serial.println("     mW");
    Serial.println("");
    Serial.print("Charge:   "); Serial.print(soc); Serial.println(" %");
    Serial.print("Voltage:   "); Serial.print(volts); Serial.println(" mV");
    Serial.print("Current:   "); Serial.print(current); Serial.println(" mA");
    Serial.println("--------------------------------------------------------");*/
    Serial.println("Values gotten");
  }
}//ISR_GetValues

Here's a screenshot of roughly what my Node-red nodes will look like: 1

1

1 Answers

2
votes

Just implement a simple serial protocol. No need to combine your sketch and Firmata.

If your PI's job is to visualize and provide a user interface all it needs to do is continuously receive values and send commands on demand.

Your Arduino continuously sends values and checkes wether it received a command.