Arduino Pachube client

Automatizace, řízení, měření, logování a programování s využitím platformy Arduino.
vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Arduino Pachube client

Příspěvek od vanous »

Pokud byste chtěli experimentovat s Pachube (pachube.com), ujistěte se, že použijete arduino IDE 1.0, nebo alespoň 1.0~beta1+dfsg-1 (debian unstable/experimental), starší verze se tvářily, že fungují, ale spojení neprocházelo. Nyní funguje standardní pachube example přímo z IDE. ušetříte si... cca jeden večer :)
vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Re: Arduino Pachube client

Příspěvek od vanous »

release early, release often :)

První testovací verze pachube upload clienta pro arduino uno s ethernet shield a 16x4 displejem.

co dělá: odesílá jednu proměnou (V) na pachube feed. vypisuje stav na displej.
co chybí: spousta. zatím testuji pouze s potenciomentrem na pin5, ne na bateriích.
závislosti: pachube účet a vytvořený feed.

#include <LiquidCrystal.h>
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

// initialize the library instance:
Client client;


/*
  Simple Solar Battery Monitor
 
 The circuit:
 Volts ( pin0) scaled input from 24vdc battery to max 5v for digitize
 Amps (pin1) input for hall effect current sensor 0 amps ~ 3.5v
 Output to 16x4 LCD display
 
 created Aug 2010 for Battery Monitor
 by Jerry Jeffress
 Adopted Dec 2011 by Petr Vanek
 - 16x4 display
 - pot for display blight and led light instead of contrast/blight pins
 - upload to Pachube
 - remove dependencies on Metro and Streaming
 - DHCP
 
 */
const int voltsInPin = 5; //voltage sensor for 24V system
const int ampsInPin = 1;
//const int backLitePin = 5; //not used
//const int contrastPin = 6; //not used
const float batterySize = 9.48; //Battery capacity in KwHrs
const float chargeEff = 0.85; //Approx Amount of power into a lead acid battery that is stored


long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
long lastLCDTime = 0;
const int postingInterval = 10000; //delay between updates to Pachube.com
const int LCDInterval = 1000; //delay between updates to Pachube.com
boolean lastConnected = false; // state of the connection last time through the main loop



//Metro oneSecond = Metro(1000);  // Instantiate an one timer
int aSecond;
int blinkit;
int bStatus; //Battery status, 0-6 states
float absorbCtr, chargeCtr, disChargeCtr, eqCtr;
float absorbTimeOut = 60*60*3.0;//3 hours in seconds
float eqTimeOut = 60*60*3.0; //3 Hours in seconds
float tenHours = 60*60*10.0;
float sec2Hr = 1.0/(1000 * 3600.0); //Convert watt-sec to kwHrs
float volts, amps, power;
float bCharge; //This is power monitor variable total effective charge to and from the battery
float bLow; //low battery value
// initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(9, 8, 5, 4, 3, 2);

void setup(){
  Serial.begin(9600); // Start the Serial communication for debug mainly
  //analogWrite(backLitePin, 64); //LCD backlite 1/4 full 20.6 ma on battery pack
  //analogWrite(contrastPin, 80); //Set LCD contrast
  aSecond = 0;
  blinkit = 0;
  bCharge = batterySize * 0.95; //init charge 95% full battery
  absorbCtr = 0;
  eqCtr = 0;
  chargeCtr = 60*9;
  disChargeCtr = 0;
  bLow = 0.5;  //Low battery warning when hattery 50% charged
  bStatus = 7;//This a an error value must be updated in Calculate bStatus
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 4);
  lcd.print("Init.....");

  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // lcd.setCursor(0,0);
    // lcd.print("Failed to configure Ethernet using DHCP");
    // lcd.setCursor(0,0);
    // lcd.print("Failed to configure Ethernet using DHCP");

    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // give the ethernet module time to boot up:
  delay(1000);




};

void loop(){
  if (millis() - lastLCDTime > LCDInterval) { // check if the metro has passed it's interval .
    //sample volt and amps from the battery
    sampleVoltsAmps();
    /* // Output serial time volts amps as to display
     Serial << aHour << _BYTE(58) << aMinute << _BYTE(58) <<
     aSecond << _BYTE(9) << volts << _BYTE(9) << amps << _BYTE(9) << bCharge << _BYTE(9) <<
     (batteryStatus
     ) << endl;
     */
    //Update LCD display each second
    calcPower();
    calcbStatus();
    newDay();

    //if(aSecond % 6 < 3)
    displayStatus();
    //else
    //displayCtr();
    //aSecond = aSecond++;
    //if (aSecond >= 60)
    // aSecond = 0;
    // ((blinkit = blinkit++;
    //if (blinkit > 1)
    // blinkit = 0;
    lastLCDTime = millis();
  }    

  if (millis() - lastConnectionTime > postingInterval){

    // if there's incoming data from the net connection.
    // send it out the serial port. This is for debugging
    // purposes only:
    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("disconnecting.");
    // client.stop();
    // }

    // if you're not connected, and ten seconds have passed since
    // your last connection, then connect again and send data:
    if(!client.connected()) {
      Serial.println("sending");
      sendData(); //data sending happens here
    }
    // store the state of the connection for next time through
    // the loop:
    lastConnected = client.connected();

  }
}

void sampleVoltsAmps() {
  int voltSum = 0.0;
  float ampSum = 0.0;
  // loop 10 time over one 50hz cycle to smooth
  for (int i = 0; i < 10; i++){
    volts = map(analogRead(voltsInPin), 0, 1023, 0, 3309); //adjust for your sensor
    voltSum = voltSum + volts;
    amps = map(analogRead(ampsInPin), 0, 1023, -806, 217); //adjust for your sensor
    ampSum = ampSum + amps;
    delay(2);
  }//end smooth loop
  //Get 10 sample average
  volts = voltSum /1000.0;  //Factor to scale to volts
  amps = ampSum * 0.015;  //Factor to scale to Amps
}

//Calc power
void calcPower(){
  power =  volts * amps;  //Units are watt-seconds
  if (power <= 0){
    bCharge = bCharge +(power * sec2Hr);
  }
  else {
    bCharge = bCharge + (power * sec2Hr * chargeEff);
  }
}
//Calculate bStatus 
void calcbStatus(){
  bStatus = 0; //This charge/discharge
  if(amps >= 0)
    chargeCtr = chargeCtr +1;
  if(amps < 0){
    disChargeCtr = disChargeCtr + 1;
  }

  //if(volts < 28.3)
  //absorbCtr = absorbCtr -1; //debug only commint
  if(absorbCtr < 0)
    absorbCtr = 0; 
  if(volts > 28.3){
    bStatus = 1;
    absorbCtr = absorbCtr + 1;
  }
  if(volts > 27.3 && absorbCtr > absorbTimeOut)
    bStatus = 2;
}
// New Day
void newDay(){
  if(disChargeCtr == tenHours) //10 hours
      chargeCtr = 0;
  if(chargeCtr > 60*10 && disChargeCtr > tenHours){
    //Serial << "Debug trap new day" << _BYTE(9) << disChargeCtr <<endl;
    disChargeCtr = 0;
    absorbCtr = 0;
    eqCtr = 0;
    //Other saves for a New Day
  }

}
//update LCD Display
void displayStatus(){

  // Print volts to LCD.
  lcd.setCursor(0,0);
  lcd.print("BAT ");
  lcd.print(volts, 1); //display volts to one decimal place
  lcd.print("V ");
  // Print % full to display
  if(bCharge < batterySize){
    lcd.print(100 * bCharge/batterySize,1);
    lcd.print("%");
  }
  else{
    lcd.print("Full ");
    bCharge = batterySize;
  }
  //Print Battery Status to Display
  lcd.setCursor(0, 1);
  switch(bStatus){
  case 0:
    if(amps >= 0)
      lcd.print("Charge ");
    else
      lcd.print("Discharge ");
    break;
  case 1:
    lcd.print("Absorb ");
    break;
  case 2:
    lcd.print("Float ");
    break;
  default:
    lcd.print("Error ");
  }
  if(bCharge < bCharge * bLow){//Battery Low blink
    if(blinkit==0)
      lcd.print("Low ");
    else
      lcd.print(" Low");
  }
  if(volts > 29.2 && eqCtr < eqTimeOut){
    lcd.setCursor(0, 1);
    lcd.print("Equalize ");
    eqCtr =eqCtr + 1;
  }
  //Print Amps to display right justified
  if(amps<0){ //All negative
    if(amps<-9.9){
      lcd.print(amps,1);
    }
    else{
      lcd.print(" ");
      lcd.print(amps,1);
    }
  }
  else { //all positive or zero
    if(amps>9.9){
      lcd.print("+");
      lcd.print(amps,1);
    }
    else{
      lcd.print(" +");
      lcd.print(amps,1);
    }
  }

  lcd.print("A");
  //}

  //Counter page
  //void displayCtr(){
  //lcd.clear();
  lcd.setCursor(0, 2);

  lcd.print("Chr ");
  lcd.print(chargeCtr/60,0);
  lcd.print(" Dis ");
  lcd.print(disChargeCtr/60,0
    );
  lcd.setCursor(0,3);
  lcd.print("Abs ");
  lcd.print(absorbCtr/60,0);
  lcd.print(" eq ");
  lcd.print(eqCtr/60,0);
}


// this method makes a HTTP connection to the server:
void sendData() {
  // if there's a successful connection:
  if (client.connect("www.pachube.com", 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request.
    // fill in your feed address here:
    client.print("PUT /api/41032.csv HTTP/1.1\n");
    client.print("Host: http://www.pachube.com\n");
    // fill in your Pachube API key here:
    client.print("X-PachubeApiKey: XXXXXXXXXXXX\n");
    client.print("Content-Length: ");

    //int thisData = analogRead(5);
    float thisData = volts;
    int thisLength = getLength(thisData);

    // calculate the length of the sensor reading in bytes:
    client.println(thisLength + 3, DEC);
    Serial.print("length: ");
    Serial.print(thisLength);

    // last pieces of the HTTP PUT request:
    client.print("Content-Type: text/csv\n");
    client.println("Connection: close\n");

    // here's the actual content of the PUT request:
    //client.print("1, ");
    client.println(thisData, DEC);
    //Serial.print("sending volts: ");
    //Serial.println(thisData);
    //Serial.print("was volts: ");
    //Serial.println(volts);


    // note the time that the connection was made:
    lastConnectionTime = millis();
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

  } 
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
  }
}


// This method calculates the number of digits in the
// sensor reading.  Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

int getLength(int someValue) {
  // there's at least one byte:
  int digits = 1;
  // continually divide the value by ten,
  // adding one to the digit count for each
  // time you divide, until you're at 0:
  int dividend = someValue /10;
  while (dividend > 0) {
    dividend = dividend /10;
    digits++;
  }
  // return the number of digits:
  return digits;
}



vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Re: Arduino Pachube client

Příspěvek od vanous »

Pokud budete chtít nahrávat program do arduina UNO připojeného přes USB k linuxové mašině z dálky, z konzole to jde lehce (v linuxu):

na mašinu s připojeným arduinem není potřeba celé arduino ide (arduino, arduino-cor) ale stačí nainstalovat avrdude:

Kód: Vybrat vše

apt-get -u install avrdude 
na místní mašině, kde vyvíjíte, se po kompilaci v arduino ide vytvoří .hex někde v tempu, třeba takto:

Kód: Vybrat vše

/tmp/build5976941872115855353.tmp/solar.cpp.hex
tak si to pošlete na ten comp s arduinem, třeba takto:

Kód: Vybrat vše

scp /tmp/build5976941872115855353.tmp/solar.cpp.hex root@192.168.3.4:/tmp/
ssh-čkujte se do té vzdálené mašiny a nahrajte do arduino takto:

Kód: Vybrat vše

avrdude -F -v -v -v -pm328p -cstk500v1 -P/dev/ttyACM0  -D -Uflash:w:/tmp/solar.cpp.hex 
šlo by to spustit i přes ssh, třeba takto:

Kód: Vybrat vše

ssh -C -v root@192.168.3.4 avrdude -F -v -v -v -pm328p -cstk500v1 -P/dev/ttyACM0  -D -Uflash:w:/tmp/solar.cpp.hex 
A nemusíte do mrazu, pokud to máte přes dvůr :)
vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Re: Arduino Pachube client

Příspěvek od vanous »

Založil jsem projekt na googlecode, viz tento oznam: https://plus.google.com/u/0/10575124820 ... Xbdij58UT8 , mimo jiné obsahuje vyčítání komunikace ze sínového Měniče MeanWell TS-1500-224B 1500W.
vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Re: Arduino Pachube client

Příspěvek od vanous »

doplnil jsem vzdálené vypínání/zapínaní měniče pomocí elegantního vypínače, viz příklad (ne můj měnič :lol: ): http://apps.pachube.com/dashboard/11475 ... 5oXCerjDig
switch.png
switch.png (3.93 KiB) Zobrazeno 5241 x
vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Re: Arduino Pachube client

Příspěvek od vanous »

Hledám I2C multirelé board, něco jako toto, nevíte o nečem?

http://www.robot-electronics.co.uk/cgi- ... %23a54#a54
vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Re: Arduino Pachube client

Příspěvek od vanous »

Vše funguje jak má, ale ethernet shield evidentně není bez chyby a pokud data posílám i přijímám tak se to umí seknout a pomůže až reset. Trochu pomohlo snížení frekvence odesílání, ale úplně pomohlo pouze odesílat a nestahovat... toš tak...
vanous
Příspěvky: 116
Registrován: sob říj 15, 2011 7:28 pm

Re: Arduino Pachube client

Příspěvek od vanous »

vanous píše:Vše funguje jak má, ale ethernet shield evidentně není bez chyby a pokud data posílám i přijímám tak se to umí seknout a pomůže až reset. Trochu pomohlo snížení frekvence odesílání, ale úplně pomohlo pouze odesílat a nestahovat... toš tak...
nebylo to ethshieldem, ale displejem - po jeho odebrání hw i z kódu mám nelimitovaný uptime...

  • Podobná témata
    Odpovědi
    Zobrazení
    Poslední příspěvek