Multiplexing, feeds and millis

Hi all.

Im trying to make a small form factor energy monitor so im using a nodemcu and multiplexing the 1 analogue input.
the goal is to send it to a dashboard and be able to get reports on daily usage and alarms etc.
Im currently trialling adafruit.io as it the highest data rate/per min I can find for free. Im updating the feeds every 2 seconds .

As its still under construction I’m simulating the analogue inputs with pots. For the prototype im using ACS712 30A current sensors, eventually ill move to current transformers. The next step is to integrate the power measurement.

here is what I currently have working:

#define IO_USERNAME    "xxxxxx"
#define IO_KEY         "xxxxxxxxxxxxxxxxxxxxxxxxx"
#define WIFI_SSID       "xxxxxxxxxxxxxxxxxxx"
#define WIFI_PASS       "xxxxxxxxxxxxxxxxxxxxxx"
#include "AdafruitIO_WiFi.h"
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);

#define MUX_A D4
#define MUX_B D3
#define MUX_C D2
#define ANALOG_INPUT A0
#include "config.h"

#define INTERVAL_MESSAGE1 2000  //is this right for a 2s delay?
#define INTERVAL_MESSAGE2 2000  

int LED1 = D0;
int LED2 = D1;
int LED3 = D5;
int LED4 = D6;
int LED5 = D7;
int LED6 = D8;


unsigned long time_1 = 0;
unsigned long time_2 = 0;
AdafruitIO_Feed *grid = io.feed("grid");  
AdafruitIO_Feed *solar1 = io.feed("solar1");
void print_time(unsigned long time_millis);


  void changeMux(int c, int b, int a)
  {
    digitalWrite(MUX_A, a);
    digitalWrite(MUX_B, b);
    digitalWrite(MUX_C, c);
  }



  
void setup() {

  // start the serial connection
  Serial.begin(115200);
 
 
  // wait for serial monitor to open
  while(! Serial);

  Serial.print("Connecting to Adafruit IO");

  // connect to io.adafruit.com
  io.connect();

  // wait for a connection
  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  // we are connected
  Serial.println();
  Serial.println(io.statusText());
{
    //Deifne output pins for Mux
  
    pinMode(MUX_A, OUTPUT);
    pinMode(MUX_B, OUTPUT);
    pinMode(MUX_C, OUTPUT);
    
 
  }


}

void loop() {
  io.run();
  
  float value;

    changeMux(LOW, LOW, LOW);

    changeMux(LOW, LOW, HIGH);
    
if(millis() > time_1 + INTERVAL_MESSAGE1){
        time_1 = millis();
        print_time(time_1);
         value = analogRead(ANALOG_INPUT); //Value of the sensor connected Option 1 pin of Mux
    Serial.print("sending -> ");
    Serial.println(value);
    solar1->save(value);
    }
         
    changeMux(LOW, HIGH, LOW);
    if(millis() > time_2 + INTERVAL_MESSAGE2){
        time_2 = millis();
        print_time(time_2);
         value = analogRead(ANALOG_INPUT); //Value of the sensor connected Option 2 pin of Mux
   Serial.print("sending -> ");
    Serial.println(value);
    grid->save(value);

  
}
   

  void print_time(unsigned long time_millis){
    Serial.print("Time: ");
    Serial.print(time_millis/1000);
    Serial.print("s - ");
}

I need to integrate some code a little like this to take power measurements :

#define CURRENT_SENSOR A0  // Define Analog input pin that sensor is attached
 
float amplitude_current;      // Float amplitude current
float effective_value;       // Float effective current
 
void setup()
{
    Serial.begin(9600);
    pins_init();
}
void loop()
{
    int sensor_max;
    sensor_max = getMaxValue();
    Serial.print("sensor_max = ");
    Serial.println(sensor_max);
    
    //the VCC on the Arduino interface of the sensor is 5v
    
    amplitude_current=(float)(sensor_max-512)/1024*5/185*1000000; // for 5A mode,you need to modify this with 20 A and 30A mode;
    effective_value=amplitude_current/1.414;
    
    //for minimum current=1/1024*5/185*1000000/1.414=18.7(mA)
    //Only sinusoidal alternating current
    
    Serial.println("The amplitude of the current is(in mA)");
    Serial.println(amplitude_current,1);
    
    //Only one number after the decimal point
    
    Serial.println("The effective value of the current is(in mA)");
    Serial.println(effective_value,1);
}
void pins_init()
{
    pinMode(CURRENT_SENSOR, INPUT);
}
/*Function: Sample for 1000ms and get the maximum value from the S pin*/

int getMaxValue()
{
    int sensorValue;    //value read from the sensor
    int sensorMax = 0;
    uint32_t start_time = millis();
    while((millis()-start_time) < 1000) //sample for 1000ms
    {
        sensorValue = analogRead(CURRENT_SENSOR);
        if (sensorValue > sensorMax)
        {
            /*record the maximum sensor value*/
            
            sensorMax = sensorValue;
        }
    }
    return sensorMax;
}

I cant get my head around the mux timing(and others) I have the mux sampling the A0 at one rate, pushing data to the dashboard feed at another and the power measurement requires sampling of 1 second to work.

Can anyone point me in the right direction for setting this up, up till now my cut n paste and my limited understanding has got me by.
I’m keen to learn so I’m not asking anyone to write the code for me but any suggestions would be really helpful.

Thanks :slight_smile:

The main loop should look something like this...

void loop() {
  readInputs();
  doCalculations();
  sendOutputs();
}]/code]

Each of those functions should run very quickly. Like a few milliseconds. If it's not time to send an output, then don't send it. Just return from the function.

Analog inputs should be read on a fixed schedule. Maybe every 10ms you advance the analog input to the next position and take a reading. You can vary that schedule. Maybe one input needs to be read twice as often, or you want to take 5 readings in a row and average them because of noise on one input.

Once you have your stream of regularly-spaced analog inputs digitized, you can do any digital signal processing required. Averaging is one example. Usually that's done as a moving-average so bringing in one new value pushes the oldest one off the back and the output of the digital filter is the average of the most-recent 10 readings.

There's lots of other digital filters that might be appropriate for each different analog input. It depends on the noise to be filtered out, frequency response desired or what useful information you want to extract from the signal.

Outputs will likely happen at a much slower rate than the analog inputs. Once per second is good for a data logger. 2 or 4 times per second makes a screen update quickly enough that it seems continuous to the eye.