HW hardware
MCU unità microprocessore
ALU unità aritmetico-logica (coprocessore matematico)
elvis:
Dovrei quindi modificare la libreria EmonLib?
No. Ti sto dicendo che la lentezza registrata potrebbe essere data proprio dalla libreria stessa e dal tipo e quantità di calcoli che essa esegue.
... quindi, mi sembra di capire, non ci posso far nulla....
Scrivi che il problema nasce nel momento in cui inserisci le letture in un altro codice.
Non è che è l'altro codice che rallenta questo e non viceversa?
Ciao,
con la libreria EmonLib ci ho giocato parecchio, di fatto ci ho aggiunto altri sensori (temperatura, luce, etc ) e shield Wifi/Eth con relative librerie.
Non ho riscontrato nessun problema.
Prova a postare il codice che utilizzi e che ti da problemi!
Fondamentalmente il mio interesse è vedere la corrente misurata dai TA su cosm im modo d'aver sotto controllo la potenza generata dal mio impianto fotovoltaico.
Ho già un codice che "gira" molto bene con il quale visualizzo su cosm i dati dell'impianto termosolare. Refresh dei dati ogni 45"... Perfetto.
Aggiungendo le poche righe per il controllo dei TA, arduino rallenta e le letture su cosm avvengono ogni 4 min. circa.
Fondamentalmente il refresh dei dati su cosm avviene ogni 250 cicli...
4 minuti non è comunque male... ma mi piacerebbe rimanere sui 45"...
Questo è il codice di partenza:
/* IDE 1.0.1
modified by Ettore Massimo Albani
*/
#include <SPI.h>
#include <Ethernet.h>
#define APIKEY "XXXXXXXXXXXXXXXXXXXXXXXXXX"
#define FEEDID XXXXXX
#define USERAGENT "TEST 2"
byte mac[] = {
0xDE, 0xAD, 0xBC, 0xEF, 0xFE, 0xBD};
IPAddress ip(192, 168, 11, 21);
EthernetClient client;
char server[] = "api.cosm.com";
unsigned long lastConnectionTime = 0;
boolean lastConnected = false;
const unsigned long postingInterval = 10000;
String DataString = "";
char Buffer[10];
int otherSensorReadingAria = 0;
int otherSensorReadingCaldaia = 0;
int otherSensorReadingResistenza2Kw = 0;
int caldaiaON = 0; //*INGRESSO digitale PER CONTROLLO WEB STATO CALDAIA
int Ventola = 0; //*INGRESSO digitale PER CONTROLLO WEB STATO VENTOLA
int ResistenzaON = 0; //*INGRESSO digitale PER CONTROLLO WEB STATO resistenza
const float AnaRef = 5.0; // valore tensione (5V)
const unsigned int Risoluzione = 1024; // risoluzione (10 bit)
const float RangeMin = 2.0; // temperatura minima °C sensore LM35DZ (alim. 5V, out con res. 2k in serie)
const float RangeMax = 100.0; // temperatura massima °C sensore LM35DZ (alim. 5V, out con res. 2k in serie)
const float Incremento = 0.01; // incremento (10 mV/°C)
float Volt = 0; // valore sensori analogici in volt
const float Isteresi = 1.0; // isteresi (1 °C)
float TempAria = 0.0; // temperatura aria
float TempAriaMin = 2.0; // soglia inferiore temperatura aria (min 2 °C = RangeMin)
float TempAriaMax = 30.0; // soglia superiore temperatura aria (max 100 °C = RangeMax)
float TempAcquaOUTtermosolare = 0.0; // temperatura acqua
float TempAcquaMin = 2.0; // soglia inferiore temperatura acqua (min 2 °C)
float TempAcquaMax = 43.0; // soglia superiore temperatura acqua (max 100 °C)
float TempAcquaINGTermosolare = 0.0; // temperatura acqua in ingresso al termosolare
extern unsigned long timer0_millis;
float mela;
void setup() {
mela=1;
analogReference(DEFAULT); // DEFAULT (5V), INTERNAL (1,1V), EXTERNAL (0÷5V)
pinMode(A0, INPUT); // NB sensore di temperatura aria
pinMode(A1, INPUT); // sensore di temperatura acqua
pinMode(A2, INPUT); // sensore di temperatura acqua ingresso termosolare
pinMode(2, OUTPUT); // D2 uscita per relè in parallelo alla resistenza da 2Kw installata sul bollitore
pinMode(3, INPUT); //*D3 ingresso controllo stato ventola da D5
pinMode(4, INPUT); //*D4 ingresso controllo stato caldaia da D6
pinMode(5, OUTPUT); //*USCITA IN PARALLELO AL RELE CALDAIA PER VISUALIZZAZIONE WEB STATO VENTOLA
pinMode(6, OUTPUT); //*USCITA IN PARALLELO AL RELE ACQUA PER VISUALIZZAZIONE WEB STATO CALDAIA
pinMode(7, OUTPUT); // relay ventola ON/OFF
pinMode(8, OUTPUT); // relay caldaia ON/OFF
pinMode(9, INPUT); // D10 ingresso per relè in parallelo alla resistenza da 2Kw installata sul bollitore
Serial.begin(9600);
if (Ethernet.begin(mac) == 0) { // start the Ethernet connection
Ethernet.begin(mac, ip); // DHCP failed, so use a fixed IP address
Serial.println("Failed to configure Ethernet using DHCP");
}
}
void loop() {
digitalWrite(2, HIGH);
Ventola = digitalRead(3);
caldaiaON = digitalRead(4);
ResistenzaON = digitalRead(9);
Volt = analogRead(A0) * 0.5;
TempAria = Volt;
delayMicroseconds(120);
Volt = analogRead(A1) * 0.5;
TempAcquaOUTtermosolare = ((Volt)+3); // temperatura acqua in °C +X°C PER COMPENSAZIONE TERMOMETRO TRIVALVOLA
delayMicroseconds(120); // 120 µs (min time reading = 100 µs x channel)
Volt = analogRead(A2) * 0.5; // valore sensore acqua in volt
TempAcquaINGTermosolare = ((Volt)+3); // temperatura acqua in °C +X°C PER COMPENSAZIONE TERMOMETRO TRIVALVOLA
delayMicroseconds(120); // 120 µs (min time reading = 100 µs x channel)
Serial.print("Temp. Aria: ");
Serial.println(TempAria, 1);
otherSensorReadingAria = Ventola;
Serial.print("Temp. Acqua: ");
Serial.println(TempAcquaOUTtermosolare, 1);
otherSensorReadingCaldaia = caldaiaON;
Serial.print("Temp. Acqua Ing Termosolare: ");
Serial.println(TempAcquaINGTermosolare);
if (TempAria > (TempAriaMax + Isteresi)) {
digitalWrite(7, HIGH); // relay ventola ON
digitalWrite(5, HIGH); //*VENTILAZIONE ATTIVATA
Serial.println("Aria calda - Ventola ON");
}
else if (TempAria < (TempAriaMax - Isteresi)) {
digitalWrite(7, LOW); // relay ventola OFF
digitalWrite(5, LOW); //*VENTILAZIONE DISATTIVATA
Serial.println("Aria fredda - Ventola OFF");
}
if ((TempAcquaOUTtermosolare > (TempAcquaMax + Isteresi)) && mela==1) (timer0_millis = 0, mela = 0 );
if (TempAcquaOUTtermosolare > (TempAcquaMax + Isteresi) && (millis()>30000)) {
digitalWrite(8, LOW); // relay caldaia OFF
digitalWrite(6, LOW); //*USCITA IN PARALLELO AL SEGNALE CALDAIA PER TELECONTROLLO
Serial.println("Acqua Calda - Caldaia OFF");
}
else if (TempAcquaOUTtermosolare < (TempAcquaMax - Isteresi)) {
digitalWrite(8, HIGH); // relay caldaia ON
digitalWrite(6, HIGH); //*USCITA IN PARALLELO AL SEGNALE CALDAIA PER TELECONTROLLO
mela=1;
Serial.println("Acqua fredda - Caldaia ON");
}
if (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting...");
client.stop();
}
if (millis() < lastConnectionTime) lastConnectionTime = millis(); // evita il blocco dopo 50gg poiché millis() si azzer
if (!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
DataString = "TempAria,";
DataString += FloatFormat(TempAria, 10, 1, false, true);
DataString += "\nVentola,";
DataString += otherSensorReadingAria;
DataString += "\nResistenzaON,";
DataString += FloatFormat(ResistenzaON, 10, 1, false, true);
DataString += "\nTempAcquaINGTermosolare,";
DataString += FloatFormat(TempAcquaINGTermosolare, 10, 1, false, true);
DataString += "\nTempAcquaOUTtermosolare,";
DataString += FloatFormat(TempAcquaOUTtermosolare, 10, 1, false, true);
DataString += "\nCaldaia,";
DataString += otherSensorReadingCaldaia;
sendData(DataString);
}
lastConnected = client.connected();
}
void sendData(String thisData) {
if (client.connect(server, 80)) {
Serial.println("connecting...");
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.cosm.com");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
client.println(thisData.length());
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
client.println(thisData);
Serial.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting...");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}
String FloatFormat(float X, char Size, unsigned char Decimal, boolean Plus, boolean AutoReduce) {
char Buffer[Size + 1];
String Z = dtostrf(X, Size, Decimal, Buffer);
if (Plus && X > 0) Z[Z.lastIndexOf(' ')] = '+';
if (AutoReduce) Z.trim();
return Z;
}
Ciao,
io sparo i dati su EmonCms (del progetto OpenEnergyMonitor) ogni 10 secondi.
Ripeto, senza problemi.
Prova a postare il tuo codice, senza quello si possono solo fare congetture.
Ora che hai postato il codice, c'è qualcosa in più su cui fare valutazioni
Ciao Pitusso,
Hai visto il codice?
Riesci a darmi qualche consigli?
Ma come fai a inviare dati su cosm ogni 10"?
Rieccomi a chiedere aiuto.
Su questo progetto sto utilizzando la libreria EmonLib trovata su openenergymonitor. Tale libreria è stata "costruita" per calcolare:
- corrente
- tensione
- potenza
EmonLib.h:
/*
Emon.h - Library for openenergymonitor
Created by Trystan Lea, April 27 2010
GNU GPL
*/
#ifndef EmonLib_h
#define EmonLib_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
class EnergyMonitor
{
public:
void voltage(int _inPinV, double _VCAL, double _PHASECAL);
void current(int _inPinI, double _ICAL);
void voltageTX(double _VCAL, double _PHASECAL);
void currentTX(int _channel, double _ICAL);
void calcVI(int crossings, int timeout);
double calcIrms(int NUMBER_OF_SAMPLES);
void serialprint();
long readVcc();
//Useful value variables
double realPower,
apparentPower,
powerFactor,
Vrms,
Irms;
private:
//Set Voltage and current input pins
int inPinV;
int inPinI;
//Calibration coeficients
//These need to be set in order to obtain accurate results
double VCAL;
double ICAL;
double PHASECAL;
//--------------------------------------------------------------------------------------
// Variable declaration for emon_calc procedure
//--------------------------------------------------------------------------------------
int lastSampleV,sampleV; //sample_ holds the raw analog read value, lastSample_ holds the last sample
int lastSampleI,sampleI;
double lastFilteredV,filteredV; //Filtered_ is the raw analog value minus the DC offset
double lastFilteredI, filteredI;
double phaseShiftedV; //Holds the calibrated phase shifted voltage.
double sqV,sumV,sqI,sumI,instP,sumP; //sq = squared, sum = Sum, inst = instantaneous
int startV; //Instantaneous voltage at start of sample window.
boolean lastVCross, checkVCross; //Used to measure number of times threshold is crossed.
int crossCount; // ''
};
#endif
Avendo io bisogno di calcolare solo la corrente come posso fare ad eliminare tutti i calcoli che il mio Arduino fa e che a me non servono e che mi rallentano solo il refresh dei dati su xively?
Riuscite a darmi un consiglio?
Grazie
EmonLib.cpp
//#include "WProgram.h" un-comment for use on older versions of Arduino IDE
#include "EmonLib.h"
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
// Sets the pins to be used for voltage and current sensors
void EnergyMonitor::voltage(int _inPinV, double _VCAL, double _PHASECAL)
{
inPinV = _inPinV;
VCAL = _VCAL;
PHASECAL = _PHASECAL;
}
void EnergyMonitor::current(int _inPinI, double _ICAL)
{
inPinI = _inPinI;
ICAL = _ICAL;
}
// Sets the pins to be used for voltage and current sensors based on emontx pin map
void EnergyMonitor::voltageTX(double _VCAL, double _PHASECAL)
{
inPinV = 2;
VCAL = _VCAL;
PHASECAL = _PHASECAL;
}
void EnergyMonitor::currentTX(int _channel, double _ICAL)
{
if (_channel == 1) inPinI = 3;
if (_channel == 2) inPinI = 0;
if (_channel == 3) inPinI = 1;
ICAL = _ICAL;
}
// emon_calc procedure
// Calculates realPower,apparentPower,powerFactor,Vrms,Irms,kwh increment
// From a sample window of the mains AC voltage and current.
// The Sample window length is defined by the number of half wavelengths or crossings we choose to measure.
void EnergyMonitor::calcVI(int crossings, int timeout)
{
int SUPPLYVOLTAGE = readVcc();
int crossCount = 0; //Used to measure number of times threshold is crossed.
int numberOfSamples = 0; //This is now incremented
// 1) Waits for the waveform to be close to 'zero' (500 adc) part in sin curve.
boolean st=false; //an indicator to exit the while loop
unsigned long start = millis(); //millis()-start makes sure it doesnt get stuck in the loop if there is an error.
while(st==false) //the while loop...
{
startV = analogRead(inPinV); //using the voltage waveform
if ((startV < 550) && (startV > 440)) st=true; //check its within range
if ((millis()-start)>timeout) st = true;
}
// 2) Main measurment loop
start = millis();
while ((crossCount < crossings) && ((millis()-start)<timeout))
{
numberOfSamples++; //Count number of times looped.
lastSampleV=sampleV; //Used for digital high pass filter
lastSampleI=sampleI; //Used for digital high pass filter
lastFilteredV = filteredV; //Used for offset removal
lastFilteredI = filteredI; //Used for offset removal
// A) Read in raw voltage and current samples
sampleV = analogRead(inPinV); //Read in raw voltage signal
sampleI = analogRead(inPinI); //Read in raw current signal
// B) Apply digital high pass filters to remove 2.5V DC offset (centered on 0V).
filteredV = 0.996*(lastFilteredV+(sampleV-lastSampleV));
filteredI = 0.996*(lastFilteredI+(sampleI-lastSampleI));
// C) Root-mean-square method voltage
sqV= filteredV * filteredV; //1) square voltage values
sumV += sqV; //2) sum
// D) Root-mean-square method current
sqI = filteredI * filteredI; //1) square current values
sumI += sqI; //2) sum
// E) Phase calibration
phaseShiftedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);
// F) Instantaneous power calc
instP = phaseShiftedV * filteredI; //Instantaneous Power
sumP +=instP; //Sum
// G) Find the number of times the voltage has crossed the initial voltage
// - every 2 crosses we will have sampled 1 wavelength
// - so this method allows us to sample an integer number of half wavelengths which increases accuracy
lastVCross = checkVCross;
if (sampleV > startV) checkVCross = true;
else checkVCross = false;
if (numberOfSamples==1) lastVCross = checkVCross;
if (lastVCross != checkVCross) crossCount++;
}
// 3) Post loop calculations
//Calculation of the root of the mean of the voltage and current squared (rms)
//Calibration coeficients applied.
double V_RATIO = VCAL *((SUPPLYVOLTAGE/1000.0) / 1023.0);
Vrms = V_RATIO * sqrt(sumV / numberOfSamples);
double I_RATIO = ICAL *((SUPPLYVOLTAGE/1000.0) / 1023.0);
Irms = I_RATIO * sqrt(sumI / numberOfSamples);
//Calculation power values
realPower = V_RATIO * I_RATIO * sumP / numberOfSamples;
apparentPower = Vrms * Irms;
powerFactor=realPower / apparentPower;
//Reset accumulators
sumV = 0;
sumI = 0;
sumP = 0;
}
double EnergyMonitor::calcIrms(int NUMBER_OF_SAMPLES)
{
int SUPPLYVOLTAGE = readVcc();
for (int n = 0; n < NUMBER_OF_SAMPLES; n++)
{
lastSampleI = sampleI;
sampleI = analogRead(inPinI);
lastFilteredI = filteredI;
filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);
// Root-mean-square method current
// 1) square current values
sqI = filteredI * filteredI;
// 2) sum
sumI += sqI;
}
double I_RATIO = ICAL *((SUPPLYVOLTAGE/1000.0) / 1023.0);
Irms = I_RATIO * sqrt(sumI / NUMBER_OF_SAMPLES);
//Reset accumulators
sumI = 0;
return Irms;
}
void EnergyMonitor::serialprint()
{
Serial.print(realPower);
Serial.print(' ');
Serial.print(apparentPower);
Serial.print(' ');
Serial.print(Vrms);
Serial.print(' ');
Serial.print(Irms);
Serial.print(' ');
Serial.print(powerFactor);
Serial.println(' ');
delay(100);
}
//thanks to http://hacking.majenko.co.uk/making-accurate-adc-readings-on-arduino
//and Jérôme who alerted us to http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
long EnergyMonitor::readVcc() {
long result;
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
ADCSRB &= ~_BV(MUX5); // Without this the function always returns -1 on the ATmega2560 http://openenergymonitor.org/emon/node/2253#comment-11432
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; //1100mV*1024 ADC steps http://openenergymonitor.org/emon/node/1186
return result;
}
Ciao Elvis..valida sta libreria..
Tornando a noi, ho notato che nello sketch della libreria EmonLib.cpp, ci sono delle delay(); cosa che nel tuo di sketch, nn ne ho viste..questo comporta rallentamenti sul ciclo di un programma..soprattutto, come nel tuo caso ce di mezzo una comunicazione seriale..
A me era capitata una cosa analoga..due sketch perfettamente funzionanti se uniti sì rallentavano a vicenda..
Bene bene, allora provo ad eliminare il delay(100) sulla libreria emonlib.cpp, ma secondo te si può eliminare un po' di cose e mantenere solo le stringhe relative al calcolo della corrente?
Devo dire che ho già fatto qualche tentativo, ma, evidentemente, cancello un po' troppa roba...
si non è mai buona cosa cancellare qualcosa dalle librerie..al max modificarle..comunque tieni presente che quelle delay(); sicuramente sono li per dare un tempo alla visualizzazione dei valori..quindi teoricamente cancellandola/e nn dovrebbe succedere niente..
prova e fammi sapere..
tu hai mai usato la shield RTC?
Ciao,
sto lavorando in questo periodo con un progettino che attualmente ha 3 sensori TA e deve crescere sino a 9.
Ad ora (quindi con 3 sensori) continuo a fare aggiornamenti ogni 10 secondi via eth (e 30 sec via gprs) senza problemi di sorta.
Nella libreria inoltre l'unico casi di delay significativo (se 100ms così si possono chiamare) si ha con la print seriale di tutte le variabili gestite, cosa che non hai motivo di utilizzare.
EDIT
io credo che il problema non risieda nella libreria in se, come già detto, ma da problemi colllaterali (overflow, memoria, etc).
Quindi, la cosa che ti consiglio di fare, è fare uso del monitor seriale e inserire nel codice in punti strategici delle print, in modo che tu possa capire in che punto del tuo codice avviene il "blocco".
Trovi poi in rete piccole funzioni che ti permettono di controllare la memoria disponibile di Arduino. Inserisci anche la chiamata a questa funzione in vari punti del tuo codice e verifica.
si quella è una prova assolutamente sensata da fare e doverosa..
ma quello che intendo io è che se nel suo programma usa dei serial.print senza usare delay, e quando va ad aggiungere il programma che ha trovato e che contiene dei serial.print però con delay, gli va a rallentare l'intero programma, anche se è solo uno il delay.
tu hai ipotizzato che potrebbe essere la memoria ma se cosi fosse il programma propio non partirebbe..
Ciao
quando va ad aggiungere il programma che ha trovato e che contiene dei serial.print però con delay
il delay è all'interno di una funzione che non è necessario che richiami
tu hai ipotizzato che potrebbe essere la memoria ma se cosi fosse il programma propio non partirebbe..
ho ipotizzato che tra le altre cose, ci potrebbero essere anche problemi di memoria.
E no, anche se ci fossero, il programma partirebbe.
Solo che il funzionamento sarebbe anomalo, ci sarebbero reset, etc
in effetti è dentro a una funzione che lui non richiama.. :. :. :.
per il discorso della memoria adesso che ci penso qualche mese fa un ragazzo aveva dei problemi anomali e alla fine il problema era che arduino aveva la memoria piena perchè il programma era troppo grande..però non gli andava a rallentare il programma, in realtà era propio strippatto, non faceva nente di quello che gli diceva di fare lui..
Devo spezzare il codice perché supera i 9500 caratteri.
Parte iniziale:
/* IDE 1.0.1
26/04/2013
controllo visibile su https://cosm.com/feeds/123206
CONTROLLO POTENZA GENERATA DAI PANNELLI FOTOVOLTAICI
CONTROLLO CONSUMI IN CASA
CONTROLLO ACCENSIONE E SPEGNIMENTO CALDAIA CON SENSORE LM35 POSIZIONATO SUL TUBO DELL'ACQUA CHE ESCE DAL BOLLITORE DEL SOLARE TERMICO
CONTROLLO TEMPERATURA ACQUAL ALL'INTERNO DEL BOLLITORE DEL SOLARE TERMICO
CONTROLLO ACCENSIONE E SPEGNIMENTO VENTOLA DI ASPIRAZIONE
CONTROLLO TEMPERATURA IN CENTRALE TERMICA
CONTROLLO TEMPERATURA ACQUA IN INGRESSO DEL BOLLITORE DEL SOLARE TERMICO
CONTROLLO ACCENSIONE RESISTENZA DA 2KW COMANDATA DA CENTRALINA IMPIANTO FOTOVOLTAICO
Ethernet shield attached to pins 10, 11, 12, 13
Arduino uno
modified by Ettore Massimo Albani
*/
#include <SPI.h>
#include <Ethernet.h>
#include "EmonLib.h" // Include Emon Library
EnergyMonitor emon1; // Create an instance CORRENTE GENERATA DAL FOTOVOLTAICO
EnergyMonitor emon2; // Create an instance CORRENTE CONSUMATA IN CASA
#define APIKEY "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // replace your Cosm api key here
#define FEEDID 123206 // replace your feed ID
#define USERAGENT "casaelvis Termosolare + Fotovoltaico" // user agent is the project name
byte mac[] = { // MAC address of Ethernet controller
0xDE, 0xBD, 0xCC, 0xEF, 0xFE, 0xBD};
IPAddress ip(192, 168, 22, 22); // IP address on your network here
EthernetClient client; // initialize the library instance:
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
// IPAddress server(216, 52, 233, 121); // numeric IP for api.cosm.com
char server[] = "api.cosm.com"; // name address for Cosm API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10000; // delay between updates to Cosm.com (10 s)
String DataString = ""; // stringa per invio dati
char Buffer[10]; // buffer per dftostr()
int otherSensorReadingAria = 0;
int otherSensorReadingCaldaia = 0;
int otherSensorReadingResistenza2Kw = 0;
int caldaiaON = 0; //*INGRESSO digitale PER CONTROLLO WEB STATO CALDAIA
int Ventola = 0; //*INGRESSO digitale PER CONTROLLO WEB STATO VENTOLA
int Resistenza = 0; //*INGRESSO digitale PER CONTROLLO WEB STATO resistenza
const float AnaRef = 5.0; // valore tensione (5V)
const unsigned int Risoluzione = 1024; // risoluzione (10 bit)
const float RangeMin = 2.0; // temperatura minima °C sensore LM35DZ (alim. 5V, out con res. 2k in serie)
const float RangeMax = 100.0; // temperatura massima °C sensore LM35DZ (alim. 5V, out con res. 2k in serie)
const float Incremento = 0.01; // incremento (10 mV/°C)
float Volt = 0; // valore sensori analogici in volt
const float Isteresi = 1.0; // isteresi (1 °C)
float TempAria = 0.0; // temperatura aria
float TempAriaMin = 2.0; // soglia inferiore temperatura aria (min 2 °C = RangeMin)
float TempAriaMax = 30.0; // soglia superiore temperatura aria (max 100 °C = RangeMax)
float TempAcquaOUTtermosolare = 0.0; // temperatura acqua
float TempAcquaMin = 2.0; // soglia inferiore temperatura acqua (min 2 °C)
float TempAcquaMax = 43.0; // soglia superiore temperatura acqua (max 100 °C)
float TempAcquaINGtermosolare = 0.0; // temperatura acqua in ingresso al termosolare
//////////////////////////////////////////////////////////////
extern unsigned long timer0_millis;
float mela;
//////////////////////////////////////////////
void setup() {
//////////////////////////////////////////////
mela=1;
//////////////////////////////////////////////
analogReference(DEFAULT); // DEFAULT (5V), INTERNAL (1,1V), EXTERNAL (0÷5V)
pinMode(A0, INPUT); // NB sensore di temperatura aria
pinMode(A1, INPUT); // sensore di temperatura acqua
pinMode(A2, INPUT); // sensore di temperatura acqua ingresso termosolare
pinMode(2, OUTPUT); // D2 uscita per relè in parallelo alla resistenza da 2Kw installata sul bollitore
pinMode(3, INPUT); //*D3 ingresso controllo stato ventola da D5
pinMode(4, INPUT); //*D4 ingresso controllo stato caldaia da D6
pinMode(5, OUTPUT); //*USCITA IN PARALLELO AL RELE CALDAIA PER VISUALIZZAZIONE WEB STATO VENTOLA
pinMode(6, OUTPUT); //*USCITA IN PARALLELO AL RELE ACQUA PER VISUALIZZAZIONE WEB STATO CALDAIA
pinMode(7, OUTPUT); // relay ventola ON/OFF
pinMode(8, OUTPUT); // relay caldaia ON/OFF
pinMode(9, INPUT); // D10 ingresso per relè in parallelo alla resistenza da 2Kw installata sul bollitore
Serial.begin(9600);
emon1.current(3, 111.1); // Current: A3 -CORRENTE GENERATA DAL FOTOVOLTAICO- input pin, calibration.
emon2.current(4, 111.1); // Current: A4 -CORRENTE CONSUMATA IN CASA- input pin, calibration.
if (Ethernet.begin(mac) == 0) { // start the Ethernet connection
Ethernet.begin(mac, ip); // DHCP failed, so use a fixed IP address
Serial.println(F("Failed to configure Ethernet using DHCP"));
}
}
Parte finale:
void loop() {
double Irms1 = emon1.calcIrms(1480); // Calculate Irms only
double Irms2 = emon2.calcIrms(1480); // Calculate Irms only
Serial.print(F("Potenza Generata dal FV Kw: "));
Serial.println(Irms1); // Irms
Serial.print(F("Potenza Consumata in Casa Kw: "));
Serial.println(Irms2); // Irms
digitalWrite(2, HIGH); // attivazione uscita D2 sempre high per controllo stato resistenza
Ventola = digitalRead(3); //*INGRESSO digitale PER CONTROLLO WEB STATO VENTOLA
caldaiaON = digitalRead(4); //*INGRESSO digitale PER CONTROLLO WEB STATO CALDAIA
Resistenza = digitalRead(9); //*INGRESSO digitale PER CONTROLLO WEB STATO resistenza
Volt = analogRead(A0) * 0.5; // valore sensore aria in volt
TempAria = Volt; // temperatura aria in °C
delayMicroseconds(120); // 120 µs (min time reading = 100 µs x channel)
Volt = analogRead(A1) * 0.5; // valore sensore acqua in volt
TempAcquaOUTtermosolare = ((Volt)+3); // temperatura acqua in °C +X°C PER COMPENSAZIONE TERMOMETRO TRIVALVOLA
delayMicroseconds(120); // 120 µs (min time reading = 100 µs x channel)
Volt = analogRead(A2) * 0.5; // valore sensore acqua in volt
TempAcquaINGtermosolare = ((Volt)+3); // temperatura acqua in °C +X°C PER COMPENSAZIONE TERMOMETRO TRIVALVOLA
delayMicroseconds(120); // 120 µs (min time reading = 100 µs x channel)
Serial.print("Temp. Acqua ING Termosolare: ");
Serial.println(TempAcquaINGtermosolare);
Serial.print(F("Temp. Acqua OUT Termosolare: "));
Serial.println(TempAcquaOUTtermosolare, 1);
otherSensorReadingCaldaia = caldaiaON;
Serial.print(F("Temp. Aria Centrale Termica: "));
Serial.println(TempAria, 1);
otherSensorReadingAria = Ventola;
if (TempAria > (TempAriaMax + Isteresi)) {
digitalWrite(7, HIGH); // relay ventola ON
digitalWrite(5, HIGH); //*VENTILAZIONE ATTIVATA
Serial.println("Aria >30°C - Ventola ON");
}
else if (TempAria < (TempAriaMax - Isteresi)) {
digitalWrite(7, LOW); // relay ventola OFF
digitalWrite(5, LOW); //*VENTILAZIONE DISATTIVATA
Serial.println(F("Aria <30°C - Ventola OFF"));
}
////////////////////////////////////////////////////////////////////////////////////////
if ((TempAcquaOUTtermosolare > (TempAcquaMax + Isteresi)) && mela==1) (timer0_millis = 0, mela = 0 );
if (TempAcquaOUTtermosolare > (TempAcquaMax + Isteresi) && (millis()>30000)) {
/////////////////////////////////////////////////////////////////////////
digitalWrite(8, LOW); // relay caldaia OFF
digitalWrite(6, LOW); //*USCITA IN PARALLELO AL SEGNALE CALDAIA PER TELECONTROLLO
Serial.println(F("Temp. Acqua Bollitore >43°C - Caldaia OFF"));
}
else if (TempAcquaOUTtermosolare < (TempAcquaMax - Isteresi)) {
digitalWrite(8, HIGH); // relay caldaia ON
digitalWrite(6, HIGH); //*USCITA IN PARALLELO AL SEGNALE CALDAIA PER TELECONTROLLO
mela=1;
Serial.println(F("Temp. Acqua Bollitore <43°C - Caldaia ON"));
}
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println(F("disconnecting..."));
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if (millis() < lastConnectionTime) lastConnectionTime = millis(); // evita il blocco dopo 50gg poiché millis() si azzera
if (!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
DataString = "TempAria,";
DataString += FloatFormat(TempAria, 10, 1, false, true);
DataString += "\nVentola,";
DataString += otherSensorReadingAria;
DataString += "\nResistenza,";
DataString += FloatFormat(Resistenza, 10, 1, false, true);
DataString += "\nTempAcquaINGtermosolare,";
DataString += FloatFormat(TempAcquaINGtermosolare, 10, 1, false, true);
DataString += "\nTempAcquaOUTtermosolare,";
DataString += FloatFormat(TempAcquaOUTtermosolare, 10, 1, false, true);
DataString += "\nCaldaia,";
DataString += otherSensorReadingCaldaia;
DataString += "\nIrms1,";
DataString += FloatFormat(Irms1, 10, 1, false, true);
DataString += "\nIrms2,";
DataString += FloatFormat(Irms2, 10, 1, false, true);
sendData(DataString);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
// this method makes a HTTP connection to the server:
void sendData(String thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {
Serial.println(F("connecting..."));
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.cosm.com");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
client.println(thisData.length());
// last pieces of the HTTP PUT request:
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.println(thisData);
Serial.println(thisData);
}
else {
// if you couldn't make a connection:
Serial.println(F("connection failed"));
Serial.println();
Serial.println(F("disconnecting..."));
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}
String FloatFormat(float X, char Size, unsigned char Decimal, boolean Plus, boolean AutoReduce) {
char Buffer[Size + 1];
String Z = dtostrf(X, Size, Decimal, Buffer);
if (Plus && X > 0) Z[Z.lastIndexOf(' ')] = '+';
if (AutoReduce) Z.trim();
return Z;
}
Subito dopo il void loop, alla riga:
double Irms1 = emon1.calcIrms(1480); // Calculate Irms only
si nota un forte rallentamento del codice, motivo per cui mi piacerebbe utilizzare la parte di libreria relativa al solo calcolo della corrente Irms ed evitare di far fare ad arduino calcoli, a virgola mobile, che non mi servono.
grazie