Sketches kombinieren (3 Sensorabfragen)

Leider schaffe ich es nicht diese beiden Scripts zu kombinieren, sodass beide Outputs erfolgen. Einzeln laufen sie. Könnt ihr mir helfen?

Script 1:

#include "EmonLib.h"
// Include Emon Library
EnergyMonitor emon1;
String zeile;

void setup()
{
  Serial.begin(9600);
  emon1.current(1, 20);             // Current: input pin, calibration
}

void loop()
{
// read the input on analog pin 0:
  float sensorValue = analogRead(A0)* (5.0 / 1023.0);
// print out the value you read:
  zeile = "{\"Input\":\"A0\", \"value\":" + String(sensorValue) + "}";
  Serial.println(zeile);

delay(500);        // delay in between reads for stability

  float Irms = emon1.calcIrms(1480);  // Calculate Irms only
  zeile = "{\"Input\":\"A1\", \"value\":" + String(Irms) + "}";
  Serial.println(zeile);

delay(500);        // delay in between reads for stability
}

Script 2:

/*
Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

Measure the liquid/water flow rate using this code. 
Connect Vcc and Gnd of sensor to arduino, and the 
signal line to arduino digital pin 2.
 
 */

byte statusLed       = 13;
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;

unsigned long oldTime;
String zeile;

void setup()
{
  
  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
   
  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{
   
   if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
      
    unsigned int frac;
    
    zeile = "{\"Input\":\"D2\", \"value\":" + String(flowRate) + "}";
    Serial.println(zeile);

    
    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
    
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

Danke Helix

Warum zeigst du uns nicht deinen Versuch die zusammen zu bringen ?
Dann fällt uns die Hilfe leichter.

Dann deine Beschreibung, was genau passieren soll und was nicht geht, inkl. der Fehlermeldung.

Edit:
Ich vermute die "delays" in deinem Sketch1 machen die Probleme. Die solltest du mit der Funktion "millis" ersetzen.
Sieh dir dazu "BlinkWithoutDelay" an.

Klar. Hier mein kombinierter Sketch. Mein Ziel ist es ca. 1x pro Sekunde alle drei Werte im json Format zu bekommen (A1, A2, D2). Aktuell gehen ab und zu die { Klammern verloren. Das kann ich mir nicht erklären. Wenn ich zu viele delays (mit und ohne millis funktion) einbaue, dann bekomme ich zu wenige Ergebnisse. Das Entfernen von den Delays hat jedenfalls keine Besserung gebracht. Anbei der Screenshot mit dem fehlerhaften seriellen Output.

/*
Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

Measure the liquid/water flow rate using this code. 
Connect Vcc and Gnd of sensor to arduino, and the 
signal line to arduino digital pin 2.
 
 */
#include "EmonLib.h"
// Include Emon Library
EnergyMonitor emon1;

byte statusLed       = 13;
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;

unsigned long oldTime;
String zeile;

void setup()
{
  
  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
  emon1.current(1, 20);             // Current: input pin, calibration 
  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{
   
   if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
      
    unsigned int frac;
    
    zeile = "{\"Input\":\"D2\", \"value\":" + String(flowRate) + "}";
    Serial.println(zeile);

    
    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
    
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
    // read the input on analog pin 0:
  float sensorValue = analogRead(A0)* (5.0 / 1023.0);
// print out the value you read:
  zeile = "{\"Input\":\"A0\", \"value\":" + String(sensorValue) + "}";
  Serial.println(zeile);

delay(500);        // delay in between reads for stability

  float Irms = emon1.calcIrms(1480);  // Calculate Irms only
  zeile = "{\"Input\":\"A1\", \"value\":" + String(Irms) + "}";
  Serial.println(zeile);

delay(500);        // delay in between reads for stability
  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

arduino.JPG

Hallo,

Also so wie ich das verstehe, ist das erste sozusagen das Hauptprgramm und das zweite ist eine erweiterte Sensor Abfrage?

Ich hab (aus zeitmangel) nur kurz drübergeschaut.

delay(500);        // delay in between reads for stability
//....
delay(500);        // delay in between reads for stability

Dadurch dauert eine loop Schleife mind. 1 Sekunde.

BlinkWithoutDelay - so wie hier:

if((millis() - oldTime) > 1000)    // Only process counters once per second
  {

Grüße,
Donny

Es sollen 3 Sensorabfragen durchgeführt werden. 2 x Analog und 1 x Digital. Alle 3 Abfragen sollen optimalerweise innerhalb 1Sekunde stattfinden.
Das ist genau meine Frage: Wie integriere ich alle 3 Abfragen in die millis() Funktion ohne, dass Zeichen abgeschnitten werden so wie jetzt.

Hi

Variablen, Die in einer ISR benutzt werden, müssen volatile declariert werden.
Zu Deinen fehlenden Zeichen kann ich mir nur vorstellen, daß die Ausgabe (9600Baud) zu lange dauert und von einem Interrupt zerstückelt wird.
Wobei das An/Abschalten des Interrupt sollte für Deine Berechnung keinerlei Bewandtnis haben.
Wieso es immer A0 trifft - kA.

MfG

Ich finde das Verhalten vom Arduino nicht ganz nachvollziebar. Nach mehreren Versuchen klappt es mit Delay (50) zwischen den analogen Sensoren.

/*
Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

Measure the liquid/water flow rate using this code. 
Connect Vcc and Gnd of sensor to arduino, and the 
signal line to arduino digital pin 2.
 
 */
#include "EmonLib.h"
// Include Emon Library
EnergyMonitor emon1;

byte statusLed       = 13;
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;

unsigned long oldTime;
String zeile;

void setup()
{
  
  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
  emon1.current(1, 20);             // Current: input pin, calibration 
  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{
   
   if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
      
    unsigned int frac;
    
    zeile = "{\"Input\":\"D2\", \"value\":" + String(flowRate) + "}";
    Serial.println(zeile);

    
    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
    
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

    // read the input on analog pin 0:
  float sensorValue = analogRead(A0)* (5.0 / 1023.0);
// print out the value you read:
  zeile = "{\"Input\":\"A0\", \"value\":" + String(sensorValue) + "}";
  Serial.println(zeile);

delay(50);        // delay in between reads for stability

  float Irms = emon1.calcIrms(1480);  // Calculate Irms only
  zeile = "{\"Input\":\"A1\", \"value\":" + String(Irms) + "}";
  Serial.println(zeile);

  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

Hi,

Ich hab ein bissi herumgespielt... naja mehrere Sensoren in verschiedenen Intervallen abzufragen ist die eine Sache, eine Sensor eigene Kalibrierungs Zeit, verkompliziert das Ganze natürlich.

So sollte es funktionieren... Ich konnte nicht wiederstehen Deinen Code gleich mit reinzukopieren. Auf Interrupts hab ich nicht berrücksichtig. Darum musst Du Dich noch kümmern. Aber zumindest sind die beiden 500 delays drausen.

#include "EmonLib.h"
// Include Emon Library
EnergyMonitor emon1;
String zeile;

// ---------------> Meine Variablen
uint16_t snsorTime1 = 1000; // 1 Sekunde
uint16_t snsorTime2 = 500; // 0,5 Sekunden
uint16_t snsorTime3 = 2000; // 2 Sekunden

uint16_t snsorCTime2 = 500; // 500ms,

unsigned long calibrationTime; // Um den Sensor 2 (sag ich mal) zu kalibrieren
unsigned long previosTime;  // im Prinzip ist das nur die oldTime Variable

bool sensorFlag;
// --------------------->

  byte statusLed       = 13;
  byte sensorInterrupt = 0;  // 0 = digital pin 2
  byte sensorPin       = 2;
  
  // The hall-effect flow sensor outputs approximately 4.5 pulses per second per
  // litre/minute of flow.
  float calibrationFactor = 4.5;
  
  volatile byte pulseCount; 
  
  float flowRate;
  unsigned int flowMilliLitres;

  //oldTime hab ich durch previosTime ersetzt, macht keinen Unterschied aber ich hab bereits so begonnen, String Zeile gibt es bereits oben

void setup() {
  previosTime = millis(); // Womöglich an anderer Stelle platzieren

  Serial.begin(115200);
  Serial.println("start");

// ------------> Ab hier Dein Zeug:
  emon1.current(1, 20);             // Current: input pin, calibration

  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
 
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

}

void loop() {

  if ((millis() - previosTime) >= snsorTime1) { // Sensor 1 Abfragen
    // Wenn möglch die Sensor Abfrage in eine Funktion auslagern IMHO
    Serial.println("Sensor 1 wird abgefragt");
//  Ersten Sensor Abfragen 

// -----------------------> Aus dem zweiten Sketch
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
       
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - previosTime )) * pulseCount) / calibrationFactor; // hier die Variable ersetzt
   
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    //oldTime = millis(); <- Das wird eigentlich bereits ganz unten abgearbeitet.
   
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
   
     
    unsigned int frac;
   
    zeile = "{\"Input\":\"D2\", \"value\":" + String(flowRate) + "}";
    Serial.println(zeile);

   
    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
   
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

// ---------------------< Ende

  }
  //  if ((millis() - previosTime) >= snsorTime2 && sensor2Flag = false) { // Sensor 2 Abfragen
  if ((millis() - previosTime) >= snsorTime2 && !sensorFlag) { // sensor2Flag = false ist auch richtig
//  Zweiten Sensor Abfragen, eigentlich kalibrieren
    Serial.println("Sensor 2 wird kalibriert");

    calibrationTime = millis();
    sensorFlag = true;

// ------------------->
// read the input on analog pin 0:
  float sensorValue = analogRead(A0)* (5.0 / 1023.0);
// print out the value you read:
  zeile = "{\"Input\":\"A0\", \"value\":" + String(sensorValue) + "}";
  Serial.println(zeile);
// ---------------------<
    
  }
  // Sensor calibration time
  if ((millis() - calibrationTime) >= snsorCTime2 && sensorFlag) { // Sensor 2 Kalibrierungs Zeit
    Serial.println("Sensor 2 wurde kalibriert und wird nun Abgefragt");

// ------------------->
  float Irms = emon1.calcIrms(1480);  // Calculate Irms only
  zeile = "{\"Input\":\"A1\", \"value\":" + String(Irms) + "}";
  Serial.println(zeile);
// ---------------------<

    sensorFlag = false;
  }
  else {
    calibrationTime = millis(); // millis speichern.
  }

  previosTime = millis(); // millis speichern.
}

Hier nochmal der leere Code, mit je einem Serial.print

uint16_t snsorTime1 = 1000; // 1 Sekunde
uint16_t snsorTime2 = 500; // 0,5 Sekunden
uint16_t snsorTime3 = 2000; // 2 Sekunden

uint16_t snsorCTime2 = 500; // 500ms,

unsigned long calibrationTime; // Um den Sensor 2 (sag ich mal) zu kalibrieren
unsigned long previosTime;  // im Prinzip ist das nur die oldTime Variable

bool sensorFlag;

void setup() {
  previosTime = millis(); // Womöglich an anderer Stelle platzieren

  Serial.begin(115200);
  Serial.println("start");

}

void loop() {

  if ((millis() - previosTime) >= snsorTime1) { // Sensor 1 Abfragen
    // Wenn möglch die Sensor Abfrage in eine Funktion auslagern IMHO
    Serial.println("Sensor 1 wird abgefragt");
//  Ersten Sensor Abfragen 

  }
  //  if ((millis() - previosTime) >= snsorTime2 && sensor2Flag = false) { // Sensor 2 Abfragen
  if ((millis() - previosTime) >= snsorTime2 && !sensorFlag) { // sensor2Flag = false ist auch richtig
//  Zweiten Sensor Abfragen, eigentlich kalibrieren
    Serial.println("Sensor 2 wird kalibriert");

    calibrationTime = millis();
    sensorFlag = true;
    
  }
  // Sensor calibration time
  if ((millis() - calibrationTime) >= snsorCTime2 && sensorFlag) { // Sensor 2 Kalibrierungs Zeit
    Serial.println("Sensor 2 wurde kalibriert und wird nun Abgefragt");

    sensorFlag = false;
  }
  else {
    calibrationTime = millis(); // millis speichern.
  }

  previosTime = millis(); // millis speichern.
}

Grüße,
Donny

Helix78:
Ich finde das Verhalten vom Arduino nicht ganz nachvollziebar. Nach mehreren Versuchen klappt es mit Delay (50) zwischen den analogen Sensoren.

Versuch mal jede Zeile in Deinem Code zu kommentieren (aber nicht nur so halbherzig) mir Hilft das manchmal ungemein. Und jedes delay muss raus. Ich weiß nicht wie lange der Sensor zum kalibrieren braucht, 500ms sind etwas viel oder ist das nur einmalig? <- Würde dann ins Setup gehören.
Aber einfach die lt. Datenblatt (??) vorgeschriebene Zeit der Sensoren zu Unterschreitten damit der Code funktioniert, ist eindeutig der flasche Weg. <- Das ist nur als Hinweis zu verstehen.

Grüße,
Donny

Du könnrest auch mal die Geschwindigkeit der seriellen Verbindung hoch setzen, z.B. auff 115200 Baud (auch den Seriellen Monitor umstellen).
Warum machst Du eigentlich für jeden Wert einen eigenen JSON? Du kannst doch alle 3 in ein JSON packen.

Gruß Tommy