Comunicação http via arduino

Boas

Estou a tentar criar um circuito para controlar a minha bomba de aquecimento/painel solar (chão radiante) através de um arduino e sondas ds18b20, pelo qual já está adiantado.

Já consegui colocar a bomba a funcionar com a diferença de 1ºC e tambe com um botão para mudar entre verão e inverno.

no entanto precisava de alguma ajuda em passar a informação para um servidor por http (domoticz, thingspeak ou emoncms) neste momento não sei como faze-lo, alguem me poderá dar umas dicas como fazer?

muito obg

Já leste os documentos no emoncms.org?

O emoncms, tanto quanto me lembro tem até bibliotecas para comunicar.

a minha dificuldade prende-se com o hardware, estou com um arduino nano e preciso de ter comunicação wifi.

Sendo assim, uma solução é o módulo ESP8266. É um módulo bastante conhecido e não terá muita dificuldade em adquiri-lo e em arranjar exemplos para o pôr em funcionamento.

luisilva: Sendo assim, uma solução é o módulo ESP8266. É um módulo bastante conhecido e não terá muita dificuldade em adquiri-lo e em arranjar exemplos para o pôr em funcionamento.

Obrigado, sou um bocado iniciante nisto podias me indicar um esquema fiavel para a ligação?

Como disse no post anterior:

É um módulo bastante conhecido e não terá muita dificuldade em adquiri-lo e em arranjar exemplos para o pôr em funcionamento.

Por isso é uma questão de usar o google. Aqui está um exemplo, mas haverá muitos mais.

Ou... e desculpa atirar isto para o ar, se tiveres entradas suficientes, podes usar o nodeMCU em vez do Arduino e ESP8266.

Basicamente, o ESP8266 é um processador... existe agora a possibilidade de o programar directamente com a IDE do Arduino, logo pode ser uma alternativa interessante para o teu projecto.

eu sei, bubulindo

tenho estado a mexer no esp8266 na 1ª e 2ª versão do meu projeto, que que vou expandindo à medida que vou tendo mais conhecimento, tenho utilizado o esp-easy. e tambem com arduino mas acho o modulo um bocado instavel em output (relés) pq as vezes faz reboot, por isso é que ando a tentar o nano. neste momento ja consegui as ligaçoes ao esp01 e receber os comandos AT, agora será a parte de queimar pestana para colocar o codigo.

A minha intenção é ter:

-2 ds18b20 em comparação - botao 3 posições para aumentar a diferença de comparação 1º/2º/3ºC - botao de seleção para colocar em Modo verao/Inverno - Lcd - botão de pressão para ligar o lcd com info do modo e temperatura atuais com timer de 10s - esp8266 para comunicar wifi para o servidor

Já estou a ficar passado com isto, farto me de ler :o e testar e ainda nao consegui meter tanto o thingspeak ou emoncms a dar…

será que alguem me pode ajudar?

O que é que já fizeste?

Amanhã já estou por casa e posso meter o meu exemplo do emoncms.org

Viva.

Talvez isto te sirva de base para o thingspeak:

#include "ThingSpeak.h" // lib da thingspeak
unsigned long myChannelNumber = xxxxx;
const char * myWriteAPIKey = "XXXXXXXXXXXXXXXXXXXX";

void setup()
{
...
ThingSpeak.begin(client);
...
}

loop()
{
...
up_think();
...
}

void up_think()
{
  ...
  ThingSpeak.setField(1, tmp);
  ThingSpeak.setField(2, hum);
  ThingSpeak.setField(3, vin);
  ThingSpeak.setField(4, ampas);
  ThingSpeak.setField(5, lux);
  // Then you write the fields that you've set all at once.
  ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
...
}

Isto é so a parte de envio dos dados para o thingspeak. O resto do codigo que tenho é para os diferentes sensores, e um RTC DS3231 que também controla o time de envio de dados, neste exemplo esta a enviar de 2 em 2 mms. A base disto foi no exemplo que vem na lib da thingspeak, WriteMultipleVoltages. O que da nisto: https://thingspeak.com/channels/56445

Neste momento nao tenho ligado nem os sensores de tensão ou corrente.

a base onde vai assentar o envio dos dados é neste sketch, estou a tentar simular em exemplos mais faceis mas não estou a conseguir, ja consegui enviar para o thingspeak à mão via serial monitor mas pelo sketch nada.
obg arssant, ainda não testei esse codigo, mas para quem experimenta o domoticz ou emoncms dificilmente volta para o thingspeak, não vejo como consultar o historico nele, por isso vai ser a minha ultima alternativa.

ve aqui a pagina do emoncms que tenho no outro modulo, por enquanto ainda não ligado a nada, mas vai servir para medir a temperatura apenas, enquanto este vou querer adicionar o controlo da bomba.

/* Este sketch lê 2 DS18B20 "1-Wire" digital
com LCD e botao 
*/ 
#include <SoftwareSerial.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>

// -----------Configurações personalizadas-------------------------
#define ONE_WIRE_BUS 3         // DS18B20 Ligado ao pin X no arduino
#define rele  13             // Relé ligado ao pin X no arduino
#define Tempo_lcd_ligado 2000 // define o tempo do lcd ligado após ligar botão (milisegundos)
#define Diferenca 1.0          // Define a diferença entre sensores para ativar relé
#define botao_lcd A3          // Escolher pin de entrada para botão
#define botao_verao A0         // escolher Modo verao/inverno
//------------------------------------------------------------------
// definir tx rx do modulo esp
SoftwareSerial ESP8266(9, 8); // RX, TX

// configura onewire para comunicar com qq dispositivo OW
OneWire oneWire(ONE_WIRE_BUS);

// Envia a referençia oneWire para Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// configura o endereço LCD I2C, descobrir endereço ver outro skecht
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  

//definir estado inicial do relé
int state1 = 0;
int state2 = digitalRead(botao_verao);
// defiinir estado inicial do botão
int buttonState = 0;

// definir endereço dos sensores de temp 1-Wire, descobrir ver outro sketch .
DeviceAddress solpainel = { 0x28, 0xFF, 0xEC, 0xDA, 0xA4, 0x15, 0x01, 0x8C };
DeviceAddress bomba = { 0x28, 0xFF, 0x2D, 0x17, 0x00, 0x16, 0x03, 0x46 };

// numero de dispositivos 1wire encontrados
int numberOfDevices;

//Variaveis para controlo logico

float   Temp1, Temp2;   //  grava para comparação

float differential1 = 0.0 ;
float differential2 = 0.0 ;
int invalidCount = 0;

//codigo corre sempre que se inicia.

void setup(void)

{
  // iniciar serial port
  Serial.begin(9600);
  // Start up the library
  Serial.println ("ligando sensores one wire");
  sensors.begin();
  
  // loocaliza os sensore one wire bus
  Serial.println("");
  Serial.print("encontrando dispositivos 1-wire...");
  Serial.println ("");
  Serial.print("encontrado ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" dispositivos.");
  lcd.begin(16,2);
  Serial.print("Ligando LCD");
  Serial.print("\n\r");
// ------- Pisca 3 vezes  -------------
  for(int i = 0; i< 3; i++)
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight(); // desligando a luz do lcd 
//-------- Escreve carateres no LCD ------------------
  lcd.setCursor(0,0);
  lcd.print("Comparador do");
  delay(1000);
  lcd.setCursor(0,1);
  lcd.print("Aquecimento");
  delay(2000);
  lcd.clear();
 // set the resolution to 10 bit 
  sensors.setResolution(solpainel, 10);
  sensors.setResolution(bomba, 10);
  //delay (1500);
  lcd.noBacklight();
 //definir pin output
   { 
  pinMode(rele, OUTPUT);
  pinMode(botao_lcd, INPUT);
  pinMode(botao_verao, INPUT); 
   }
  delay (1000);
}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    Serial.print("Erro a obter temperatura");
  } else {
    Serial.print("C: ");
    Serial.print(tempC);
    }
}
void loop(void)
{
   Serial.print("A atualizar temperaturas...\n\r");
  sensors.requestTemperatures();
  
  Serial.print("Temp do painel: ");
  printTemperature(solpainel);
  Serial.print("\n\r");
  Serial.print("Temp da bomba: ");
  printTemperature(bomba);
  Serial.print("\n\r");
  Serial.println(""); 
  Serial.println("");
  Serial.print ("estado do rele: ");
  Serial.println(state1);
  Serial.println("");
  
  buttonState = digitalRead(botao_lcd);
 
    if (buttonState == HIGH){
      // Botao pressionado.
      Serial.println("Botao pressionado - HIGH");
      lcd.on();
      lcd.setCursor(0,0);
      buttonState = digitalRead(botao_verao);
       if (buttonState == HIGH) {
        lcd.print("Modo: Verao");}
       else {
        lcd.print("Modo: Inverno");
       }
      delay (1000);
      lcd.setCursor(0,0);
      lcd.print("T.Entrada:");
      lcd.print(sensors.getTempC(bomba));
      lcd.setCursor(15,0);
      lcd.print("C");
     lcd.backlight();
      lcd.setCursor(0,1);
      lcd.print("T.Painel :");
      lcd.print(sensors.getTempC(solpainel));
      lcd.setCursor(15,1);
      lcd.print("C");
      delay (Tempo_lcd_ligado);
      lcd.clear();
      lcd.off();
      
    }
    else{
      // botao nao pressionado.
      Serial.println("Botao nao pressionado - LOW");
    
    }
//Sensors for logic
Temp1 = sensors.getTempC(bomba);
Temp2 = sensors.getTempC(solpainel);

     
     //diferença entre Solpainel e bomba
      differential1 = Temp2-Temp1;
      differential2 = Temp1-Temp2;
      Serial.print("Diferenca para inverno e:");
      Serial.println(differential1);
      Serial.println("");
      Serial.print("Diferenca para Verao e:");
      Serial.println(differential2);
      Serial.println("");
      
      //logic1
     {
      buttonState = digitalRead(botao_verao);
     if (buttonState == HIGH){
       
       if (differential2 >= (Diferenca)) { // comparara temps,
        (state2 = 1);     
        digitalWrite(rele, LOW);    
        Serial.print("bomba verao ligada");
        Serial.print("\n\r");}
       else {
        (state2 = 0);
        digitalWrite(rele, HIGH);
        Serial.print("bomba verao desligada");
        Serial.println("");
        Serial.print("\n\r");}}
     else {        
       if (differential1 >= (Diferenca)) { // compara temps,
        (state1 = 1);     
        digitalWrite(rele, LOW);    
        Serial.print("bomba inverno ligada");
        Serial.print("\n\r");}
       else {
        (state1 = 0);
        digitalWrite(rele, HIGH);
        Serial.print("bomba inverno Desligada");
        Serial.println("");
        Serial.print("\n\r");}
          }
     } 
     
delay (1000);
}

maluko:
obg arssant, ainda não testei esse codigo, mas para quem experimenta o domoticz ou emoncms dificilmente volta para o thingspeak, não vejo como consultar o historico nele, por isso vai ser a minha ultima alternativa.

Viva.
Esses dois que referencias, andei por la a ver, mas nao era o que pretendia.
Tambem testei mais 2 o ploty e o exosite.
O plotly na altura que testei tinha alguns bugs chatos com clientes arduino, e nao foi pratico par o que pretendia.
o Exosite, 5* muita coisa, mas algo mais elaborado nas suas configurações, e sem tempo e pouca pachora para ver tudo, deixei tb de parte.

O thingspeak, simples e o ideal. Em 5-10mms pões aquilo a funcionar, e era o que pretendia: visualizações em tempo real. Alem disso tem uma app para android de visualização muito interessante.
O historico no thingspeak, 4 opcoes:

  • alteras o n de entradas que o gráfico apresenta de 50 para XXXX
  • crias um pluging para representar todas as entradas num mesmo grafico ou graficos independentes, similar ao exemplo que referistes e defines o n de valores a apresentar.
  • cada grafico individual podes copiar o link e alter o tamanho ( altura, largura-temporal )

http://api.thingspeak.com/channels/56445/charts/1?width=750&height=560&results=260&dynamic=true&type=spline&yaxis=ºC&title=Temperatura

with=750 height=560 results=260 o defaults sao 450-260-60

  • fazes login, exportas os dados para cvs e importas par um gráfico do excel.

E gosto mais das gauges do thingspeak:
Consegues alterar a escala geral, a escala de maximos e medios.

gauge.png

/*
Receptor RF. 
This will receive data and send it over to the interwebs... or my own data server. 

Noticed that there is cross talk. 
Channel 0 sends data... we read the pipe number, but if there is data received from another node... 
the data is overwritten in the buffer, but the node number remains the same. 

Added a field for node number in the telegram. 

TO DO: 

- Add timeout for the communication to detect error. 
- Detect sensor error. 

*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <Ethernet.h>

#define DEBUG  0 //troubleshooting

#define MSG_LEN  7
#define LOG_INTERVAL  10000 //10 seconds. 
#define TIMEOUT      50000
#define NODE_NUM  6



byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip( 192, 168, 1, 84 );

EthernetClient client;
static char server[] = "www.emoncms.org";    // name address for Google (using DNS)

RF24 radio(A2,A3);
//RF24 radio(49,53);//CE, CSN

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[6] = { 0xC0C0C0C0E0LL, 0xF0F0F0F0E1LL, 0xF0F0F0F0E2LL, 0xF0F0F0F0E3LL, 0xF0F0F0F0E4LL, 0xF0F0F0F0E5LL };


float temperatura [7]; //temperatures from pipes will be saved here. 
float Aux [7];    //not sure if these will be used. 

unsigned long timeout[7]; //added v2

unsigned char BMP_present = 0; 
Adafruit_BMP085 bmp;

unsigned long log_timer = 0; 
unsigned long self_timer = 0; 


void setup(void)
{
//  pinMode (53, OUTPUT);  //Changed. 
  pinMode (4, OUTPUT);   //SD select pin.
  digitalWrite(4, HIGH); 
  Ethernet.begin(mac);
  Serial.begin(57600);
  Serial.println("setup");
  unsigned char i = 0;
  
//initialize all variables... it's good policy.   
  for (i = 0; i< 6; i++) {
    temperatura[i] = 30.0 + i;
    Aux[i] = 30.0;
  }

//start BMP
  BMP_present = bmp.begin(); //if BMP not present... don't try to write... 
//start radio  
  radio.begin();

// optionally, increase the delay between retries & # of retries
  radio.setRetries(15,15);
//radio.openWritingPipe(pipes[1]);
  radio.openReadingPipe(0,pipes[0]);
  radio.openReadingPipe(1,pipes[1]);
  radio.openReadingPipe(3,pipes[3]);

//start Listening to others. 
  radio.startListening();
}

unsigned char channel = 0; 
void loop(void)
{
  unsigned char pipe_num = 20;
  char received[MSG_LEN]; //header and floating point value. 
  
  //read BMP data... no need to go crazy, the update will be done later. 
  if (BMP_present) {
    temperatura[NODE_NUM] = bmp.readTemperature();
    Aux[NODE_NUM] = bmp.readPressure()/100; //mBar reading. 
  }

  if (millis() - self_timer > 30000) {  
    sendData(6, temperatura[6], Aux[6]);
    log_timer = millis(); //add the processing time to cycle time. 
  }

  if (millis() - log_timer > LOG_INTERVAL) {  
    sendData(channel, temperatura[channel], Aux[channel]);
    if (++channel == 3) channel = 0; 
    log_timer = millis(); //add the processing time to cycle time. 
  }
  
  
  //RF Comms... 
  // if there is data ready
  if ( radio.available(&pipe_num) ) {
     //Serial.print("here");
    if (pipe_num < 6) { //if the pipe number is valid (just to be on the safe side)    
      // Dump the payloads until we've gotten everything
      bool done = false;
      //Serial.print(pipe_num);
      while (!done)
        {
        // Fetch the payload, and see if this was the last one.
        done = radio.read(received, MSG_LEN);
        }
        
      pipe_num = received[1];  
        
      //if received temperature
      if (received[2] == 'T') { //Temperatura
        memcpy(&temperatura[pipe_num], &received[3], 4);
      }     
      //if received humidity... 
      if (received[2] == 'H') { //Temperatura
        memcpy(&Aux[pipe_num], &received[3], 4);
      
      }
      //if received Event... 
      if (received[2] == 'E') { //Event
        //error code = received[4]; //unsigned char value. 
      }    
      //add other stuff here. 
      timeout[pipe_num] = millis(); 
      
    } //end if pipe_num < 6
  }//end if ( radio.available(&pipe_num) )
}//end loop()

/*
void SerialComms() {

  if (Serial.available()) { //someone's on the phone. 
    switch (Serial.read()) {
      case 's': //print statistics
      //temperatures...   
        for (unsigned char i = 0; i <7; i++) {
          Serial.print("temperature[");
          Serial.print(i);
          Serial.print("] = ");
          Serial.println(temperatura[i]);
        }
        Serial.print("Pressure = ");
        Serial.print(pressao/100.0);
        Serial.println(" mbar");
        //no humidity yet.... 
        
        break;
      case 'r':
        //Serial.println("received n");
        //add the nRF statistics??? 

        break;
      default:
//        Serial.println("not sure what to do here"); 
          //Serial.println(radio.getPayloadSize());
          Serial.println(radio.read_register(CONFIG), HEX);
          Serial.println(radio.read_register(EN_AA), HEX);
          Serial.println(radio.read_register(EN_RXADDR), HEX);
          Serial.println(radio.read_register(SETUP_AW), HEX);
          Serial.println(radio.read_register(SETUP_RETR), HEX);
          Serial.println(radio.read_register(RF_CH), HEX);
          Serial.println(radio.read_register(RF_SETUP), HEX);          
        break;
    }//end switch  
  }
}
*/
void sendData(unsigned char node, float temperature, float pressure) {

  client.connect(server, 80);
  delay(1000);
  //added V2
  unsigned char err; 
  
  if (millis() - timeout[node] > TIMEOUT || temperature < -200.0 || pressure < -200.0) err = 1; 
  else err = 0;
 
 //--- finish added
 
  if (client.connected() ) {
    Serial.print("Connected");
    Serial.println(node);//2
   //http://emoncms.org/input/post.json?node=0&apikey=717080df2f243bd656f1231dd7ce1b08&json={Temp:6.0}
    // send the HTTP GET request:   
    client.print("GET /emoncms/input/post.json?");
    client.print("apikey=xxxxxxxxxxxxxxxxxxxxxxxxxxx&node=");
    client.print(node);
    client.print("&json={Temp:");
    client.print(temperature);
    client.print(",Aux:");
    client.print(pressure);
    client.print(",Error:");
    client.print(err);
    client.print("}");
//    client.print("&apikey=");
//    client.print(apikey);   
//    client.println(" HTTP/1.1");
    client.println();
    delay(1500);
    while (client.available()) Serial.print((char)client.read());
    client.stop();
  }//if(client.connect(server, 80)
  else {
    // if you couldn't make a connection:
    Serial.println("Connection failed");
    Serial.println("Disconnecting...");
    client.stop();
  }//else
  delay(2000);
  while (client.available()) Serial.print((char)client.read());
  
}//sendData

Cá está o meu exemplo… não é muito bonito, ou bonito sequer mas não mexi mais nisto e entretanto desliguei o sistema.
Certamente uqe pode ser melhorado (tenho noção disso), mas como está, estava a funcionar com o emoncms.org. Não me lembro exactamente da configuração, mas no emoncms.org, isso pode ser feito depois dos dados começarem a ser recebidos.