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++;
}
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++;
}
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.
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.
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++;
}
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.
}
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.
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.