zondag 17 april 2016

ESP8266 en DHT22

UPDATE: Ik was vergeten erbij te zetten dat je een library nodig hebt om makkelijk met de DHT22 te kunnen werken, ik heb dit nu toegevoegd, voor de sketch.

Nu de ESP8266 werkt, gaan we verder en ga ik de DHT22 aansluiten om te zien of ik dat ook werkend krijg.

Ik heb de DHT22 aangesloten op het ESP8266 Yellow-board.

DHT22     ESP8266
Pin 1         VCC
Pin 2         GPIO2
Pin 3         -
Pin 4         GND

In de Arduino IDE de volgende Sketch gemaakt (Aangepast op de versie van Adafruit) Heb uiteraard de OTA update mogelijkheid weer toegevoegd, dat werk lekker makkelijk en snel, tevens heb ik de temperaturr van Fahrenheit aangepast zodat hij Celcius en Fahrenheit weergeeft.

Arduino IDE

om makkelijk met de DHT22 (of DHT11) te kunnen werken in Arduino, is er door Adafruit een library gemaakt.
Als je de Aduino IDE hebt draaien sluit deze dan nu eerst af.
Deze kun je downloaden op https://github.com/adafruit/DHT-sensor-library, rechts op de pagina boven de bestanden staat een knop [Download ZIP]
Vervolgens pak je de map en bestanden in de zip uit naar de map arduino\libraries\ welke je kan vinden in je Documenten map (normaal geproken "Mijn Documenten" of "Documenten" geheten)
Nu kan je de Arduino IDE weer opstarten en de volgende sketch maken.

Sketch

/* DHTServer - ESP8266 Webserver with a DHT sensor as an input
   Based on ESP8266Webserver, DHTexample, and BlinkWithoutDelay (thank you)
   Version 1.0  5/3/2014  Version 1.0   Mike Barela for Adafruit Industries
*/
#include <esp8266wifi.h>
#include <wificlient.h>
#include <esp8266webserver.h>
#include <arduinoota.h>
#include <wifiudp.h>
#include <dht.h>
#define DHTTYPE DHT22
#define DHTPIN  2
 
const char* ssid = "SSID";
const char* password = "SSID_PASSWORD";

ESP8266WebServer server(80);
 
// Initialize DHT sensor 
// NOTE: For working with a faster than ATmega328p 16 MHz Arduino chip, like an ESP8266,
// you need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// This is for the ESP8266 processor on ESP-01 
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
 
float humidity, temp_f, temp_c;  // Values read from sensor
String webString="";     // String to display
String webString1="";     // String to display
String webString2="";     // String to display
// Generally, you should use "unsigned long" for variables that hold time
unsigned long previousMillis = 0;        // will store last temp was read
const long interval = 2000;              // interval at which to read sensor
 
void handle_root() {
  webString= "Hello from the weather esp8266, read from /temp or /humidity";
  server.send(200, "text/plain", webString);
  delay(100);
}
 
void setup(void)
{

  // You can open the Arduino IDE Serial Monitor window to see what the code is doing
  Serial.begin(115200);  // Serial connection from ESP-01 via 3.3v console cable
  dht.begin();           // initialize temperature sensor
 
  // Connect to WiFi network
  WiFi.begin(ssid, password);
  Serial.print("\n\r \n\rWorking to connect");
 
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("DHT Weather Reading Server");
  Serial.println("Versie: " + versie);
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
   
  server.on("/", handle_root);
  
  server.on("/temp", [](){  // if you add this subdirectory to your webserver call, you get text below :)
    gettemperature();       // read sensor
//    webString1="Temperature: "+String((int)temp_f)+" F";   // Arduino has a hard time with float to string
//    webString2="Temperature: "+String((int)temp_c)+" C";   // Arduino has a hard time with float to string
    webString1="Temperature: "+String(temp_f)+" F";   // Arduino has a hard time with float to string
    webString2="Temperature: "+String(temp_c)+" C";   // Arduino has a hard time with float to string
    webString=webString1 + "\n" + webString2;
    server.send(200, "text/plain", webString);            // send to someones browser when asked
  });
 
  server.on("/humidity", [](){  // if you add this subdirectory to your webserver call, you get text below :)
    gettemperature();           // read sensor
//    webString="Humidity: "+String((int)humidity)+"%";
    webString="Humidity: "+String(humidity)+"%";
    server.send(200, "text/plain", webString);               // send to someones browser when asked
  });
  
  server.begin();
  Serial.println("HTTP server started");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
    for (int i=0;i<30;i++)
      {
        analogWrite(12,(i*100) % 1001);
        delay(150);
        analogWrite(12, 0);
        analogWrite(13,(i*100) % 1001);
        delay(150);
        analogWrite(13, 0);
        analogWrite(15,(i*100) % 1001);
        delay(150);
        analogWrite(15, 0);
      }
    Serial.println("\nRebooting....");
    delay(50);
  });

  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Sketch size: ");
  Serial.println(ESP.getSketchSize());
  Serial.print("Free size: ");
  Serial.println(ESP.getFreeSketchSpace());
  Serial.print("Chip size: ");
  Serial.println(ESP.getFlashChipSize());
  pinMode(0, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
  digitalWrite(0, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(12, LOW);
  digitalWrite(13, LOW);
  digitalWrite(14, HIGH);
  digitalWrite(15, LOW);
  digitalWrite(16, HIGH);

}
 
void loop(void)
{
  server.handleClient();
  ArduinoOTA.handle();
} 
 
void gettemperature() {
  // Wait at least 2 seconds seconds between measurements.
  // if the difference between the current time and last time you read
  // the sensor is bigger than the interval you set, read the sensor
  // Works better than delay for things happening elsewhere also
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    // save the last time you read the sensor  
    previousMillis = currentMillis;   
 
    // Reading temperature for humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
    humidity = dht.readHumidity();          // Read humidity (percent)
    temp_f = dht.readTemperature(true);     // Read temperature as Fahrenheit
    temp_c = dht.convertFtoC(temp_f);
    // Check if any reads failed and exit early (to try again).
    Serial.println(String(temp_c) + " C   " + String(humidity) + " %   " + String(temp_f) + "F");
    if (isnan(humidity) || isnan(temp_f)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
  }
}
Als deze sketch geüpload is (hoe je OTA je sketch kan uploaden kan je lezen in mijn blog bericht :
ESP8266), kan je eventueel met een FTDI-kabel en Putty zien welk IP-adres de ESP8266 heeft gekregen (Je zou ook FING - Network Tools  kunnen gebruiken op je smartphone of tablet).

Als je nu vervolgens een browser opent en gaat naar het IP-adres van de ESP8266, zie je de volgende regel "Hello from the weather esp8266, read from /temp or /humidity".
Als je nu naar IP-adres/temp of IP-adres/humidity gaat, zal je de gemeten temperatuur (Fahrenheit en Celsius) of luchtvochtigheid zien (Omdat de sketch iedere 2 seconden de waarden uitleest uit de DHT22, kan je iedere 2 seconden de pagina verversen om de nieuwe waarden te zien.


maandag 11 april 2016

ESP8266

ESP8266-12F
Ik wil graag weten hoe warm het in ieder vertrek in mijn huis is en zocht daarvoor een handige methode. Op internet kwam ik steeds meer tegen over de ESP8266, die onder andere met Arduino te programmeren is dus henb ik er maar eens een paar aangeschaft, samen met een paar DHT11's en andere onderdelen om het aan de praat te krijgen op een batterij.
Breakoutbordje

Naast een aantal standaard ESP8266-12F modules met 4MB flash heb ik tevens een breakoutbordje voor deze module en een ontwikkelbordje met batterijvoeding besteld. Toen ik het pakket binnenkreeg eerst maar eens gaan spelen met het ontwikkelbordje.

Ontwikkelbordje met batterijvoeding
Ondanks dat er op internet veel over het bordje te vinden is, was niets dat ik vond compleet, dus ga ik hier maar eens alles samenvatten en completeren.

ESP8266 (AI-Thinker of Yellow bord)


Het bordje komt met daarop ai-thinker vooraf geladen. en kan je er direct mee gaan spelen met je telefoon of tablet (voor Android hier te vinden).
(GPIO) aansluitingen
Het bordje is uitgerust met een batterijhouder voor 3 AA-batterijen, 1 blauwe (voeding) led, 6 rode leds (op GPIO 0, 2, 4, 5, 14 en 16, let op de eerst 2 zijn gedraaid, dus de eerste led zit op GPIO2 en de tweede op GPIO0), en RGB-led (op GPIO12 (groen of rood), GPIO13 (Blauw), en GPIO15 (Rood of Groen) en een LDR op de ADC (A0).

AI-Thinker

Om er nu mee te gaan spelen zet je de jumper op het bordje open en stopt 3 AA-batterijen in de houder.
Hierna zoek je op je telefoon/tablet naar een nieuw wifi-netwerk met de naam AI-THINKER_XXXXXX (waarbij XXXXXX een deel van het mac-adres is), als je hiermee verbind heb je een wachtwoord nodig (dat is dus "ai-thinker").

Hierna kan je met de app de led's aansturen en kan je de wifi instellingen wijzigen zodat het bordje verbind met jouw eigen wifi-netwerk (eventueel kan je ook de rode en groene aansturing van de RGB-led omwisselen, omdat deze bij sommige bordjes ook gewisseld is.

Dit werkt uitstekend, binnen 5 minuten had is dit wel gezien, op naar de volgende stap, Het bordje programeren met Arduino.

Arduino IDE (Serieel)


Nieuwe software op het bordje plaatsen kan met een FTDI-kabel aangesloten op de TXD, RXD, en GND pennen naast de aansluiting van de batterij.

Ik heb gebruik gemaakt van de Arduino software (versie 1.6.8 momenteel).
Na installatie en opstarten, moeten we eerst nog wat dingen aanpassen, willen we kunnen werken met de ESP8266.

We beginnen met in het menu te kiezen voor Bestand, dan Voorkeuren, in het scherm wat zich nu opent, vullen we achter "Additionele Bordenbeheerder URLs" de volgende URL in:
http://arduino.esp8266.com/versions/2.1.0/package_esp8266com_index.json.

Mocht er al wat ingevuld staan, klik dan eerst op het icoontje wat rechts van het invoerveld staat, er opend dan een groter edit-venster, waarbij je op iedere regel een URL kan invullen. We bevestigen daarna met [OK] (2x als je de grotere edit geopend had).
Nu openen we het menu Hulpmiddelen, Board: "Huidig geselecteerd bord"Bordenbeheerder....
In het venster "Bordenbeheerder" wat zich nu opent, typ je in Filter je zoekresultaten... "ESP8266" (Uiteraard zonder de quootjes), Nu staat er in het venster "esp8266 by ESP8266 Community", selecteer de door er met de muis op te klikken en kies [Installeren].
Als deze geïnstalleerd is, kan je het venster sluiten en kunnen we de juiste instellingen voor ons bord maken.

Kies wederom voor Hulpmiddelen, Board: "Huidig geselecteerd bord", scrol eventueel naar beneden en kies onder ESP8266 Modules ,voor de "Generic ESP8266 Module", als je nu weer Hulpmiddelen opent, zal je zien dat er veel meer opties staan.
We maken hier (in mijn geval) de volgende instellingen:
Upload using: Serial(De eerste keer zullen we in ieder geval de sketch via de FTDI-kabel moeten laden.
Flash Size: 4M (1M SPIFFS)(dit is de grootte van het Flashgeheugen van de module, deze MOET goed staan wil je ook OTA (Over The Air, via wifi dus) de sketch kunnen updaten).
Upload Speed: 115200Hierover hieronder meer.
Poort: ComXSelecteer de poort waarop de FTDI kabel is aangesloten.
Nu kan je via Bestand, Voorbeelden, ArduinoOTA, het voorbeeld BasicOTA laden. Pas regels 6 en 7 aan zodat jouw eigen ssid en wachtwoord daar staan ingevuld op de plaats van de puntjes.

Nu kan je in principe de uploaden op het bordje, bij mij mislukte dat steeds door 2 redenen:
  1. De snelheid van de seriele poort was niet goed.
  2. Ik deed de reset van het bordje niet goed.
Om de ze punten op te lossen dien je het volgende te doen:
  1. In apparaatbeheer moet je de Seriele poort opzoeken die de FTDI-kabel heeft, daar stel je de snelheid in op 115200 bits. Bij mij moest dit althans gebeuren, anders kreeg ik niets geupload naar de ESP8266.
  2. Om het bordje te resetten voor het uploaden van een sketch, trek je 1 batterij los, sluit de jumper. Nu sluit je de batterij weer aan en haal je vervolgens de jumper los.
 Nu kan je de sketch uploaden naar de ESP8266.

Als dit allemaal goed is gegaan kan je met bv Putty een verbinding opzetten naar de ESP8266 om zo de output van de seriële monitor te zien.
Hiervoor kies je in Putty voor Connection Type: "Serial", Serial Line: "ComX" en de Speed: "115200".
Als je nu de port opent en de ESP8266 even reset (door een batterij los te halen en er weer in te zetten, zal je nu als het goed is een IP adres zien verschijnen in Putty.

Als dit allemaal werkt heb je je eerste sketch geladen op de ESP8266.

Arduino IDE (OTA)

Maar nu gaan we een stapje verder, via OTA de sketch laden.
Wijzig bij Hulpmiddelen, Upload Using in "OTA" en Poort in "esp8266-[ChipID] at IP-adres (Generic ESP8266 Module)", mocht deze poort er niet tussen staat, sluit dan de Arduino software af en start hem opnieuw op (zorg wel dat de ESP8266 AAN staat), nu zal de poort er als het goed is wel tussen staan.

Om een sketch via OTA te kunnen laden moet er vrije ruimte op de ESP8266 zijn om de nieuwe sketch op te slaan naast de oude sketch, de ruimte gereserveerd voor sketches wordt aangegeven in de SPIFFS, bij mij dus 3MB, de oude en de nieuwe sketch kunnen beide dus 1,5 MB groot zijn maximaal.

Nu is het heel simpel, kies upload in de Arduino en de sketch zal geladen worden, dit kan je ook volgen in Putty als je die nog open hebt staan.

Bestudeer zelf de BasicOTA sketch maar om te zien hoe het 1 en ander werkt en wat je nog kan instellen / aanpassen.
Zelf heb ik via OTA de volgende aangepaste BasicOTA sketch geladen:

Sketch

#include <esp8266wifi.h>
#include <esp8266mdns.h>
#include <wifiudp.h>
#include <arduinoota.h>

const char* ssid = "SSID";
const char* password = "SSID_PASSWORD";
int val = 0;
int analog = A0;

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 8266
  ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("MyEsp8266");

  // No authentication by default
//  ArduinoOTA.setPassword((const char *)"123");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Sketch size: ");
  Serial.println(ESP.getSketchSize());
  Serial.print("Free size: ");
  Serial.println(ESP.getFreeSketchSpace());
  Serial.print("Chip size: ");
  Serial.println(ESP.getFlashChipSize());
  pinMode(0, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
}

void loop() {
  ArduinoOTA.handle();
  Serial.print("Led 1 -");
  digitalWrite(2, LOW);
  delay(750);
  digitalWrite(2, HIGH);
  Serial.print(" Led 2 -");
  digitalWrite(0, LOW);
  delay(750);
  digitalWrite(0, HIGH);
  Serial.print(" Led 3 -");
  digitalWrite(4, LOW);
  delay(750);
  digitalWrite(4, HIGH);
  Serial.print(" Led 4 -");
  digitalWrite(5, LOW);
  delay(750);
  digitalWrite(5, HIGH);
  Serial.print(" Led 5 -");
  digitalWrite(14, LOW);
  delay(750);
  digitalWrite(14, HIGH);
  Serial.print(" Led 6 -");
  digitalWrite(16, LOW);
  delay(750);
  digitalWrite(16, HIGH);
  Serial.print(" Led Green -");
  digitalWrite(12, HIGH);
  delay(750);
  digitalWrite(12, LOW);
  Serial.print(" Led Blue -");
  digitalWrite(13, HIGH);
  delay(750);
  digitalWrite(13, LOW);
  Serial.print(" Led Red =");
  digitalWrite(15, HIGH);
  delay(750);
  digitalWrite(15, LOW);
  delay(500); 
  val = analogRead(analog); 
  Serial.print(" LDR value: ");
  Serial.println(val);

  ArduinoOTA.handle();

  Serial.print("Led 1 -");
  digitalWrite(2, LOW);
  delay(500);
  Serial.print(" Led 2 -");
  digitalWrite(0, LOW);
  delay(500);
  Serial.print(" Led 3 -");
  digitalWrite(4, LOW);
  delay(500);
  Serial.print(" Led 4 -");
  digitalWrite(5, LOW);
  delay(500);
  Serial.print(" Led 5 -");
  digitalWrite(14, LOW);
  delay(500);
  Serial.print(" Led 6 -");
  digitalWrite(16, LOW);
  delay(500);
  Serial.print(" Led Green -");
  digitalWrite(12, HIGH);
  delay(500);
  Serial.print(" Led Blue -");
  digitalWrite(13, HIGH);
  delay(500);
  Serial.print(" Led Red =");
  digitalWrite(15, HIGH);
  delay(500);  
  digitalWrite(2, HIGH);
  delay(150);  
  digitalWrite(0, HIGH);
  delay(150);  
  digitalWrite(4, HIGH);
  delay(150);  
  digitalWrite(5, HIGH);
  delay(150);  
  digitalWrite(14, HIGH);
  delay(150);  
  digitalWrite(16, HIGH);
  delay(150);
  digitalWrite(12, LOW);
  delay(150);
  digitalWrite(13, LOW);
  delay(150);
  digitalWrite(15, LOW);
  delay(150);
  val = analogRead(analog); 
  Serial.print(" LDR value: ");
  Serial.println(val);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Sketch size: ");
  Serial.println(ESP.getSketchSize());
  Serial.print("Free size: ");
  Serial.println(ESP.getFreeSketchSpace());
  Serial.print("Chip size: ");
  Serial.println(ESP.getFlashChipSize());
}
De leds zullen nu om de beurt oplichten (met melding in Putty) en tevens zal in Putty de waarde van de LDR getoond worden.

Zoals je kan zien heb ik (nog) geen wachtwoord ingesteld op regel 29, dit omdat ik dat nog niet aan de praat heb gekregen, Arduino vraagt netjes om het wachtwoord, echter hij accepteert het ingegeven wachtwoord daarna niet.

In het volgende blog meer over het uitlezen van de DHT11 met de ESP8266.

zondag 6 december 2015

Smart Meter Dashboard (1) - Uitlezen Chint Omvormer

Samen met een vriend zijn we een eigen (verbeterde) versie aan het maken van het Smart Meter Dashboard.
Hij is bezig met de Web-pagina's en ik hou me bezig met de Python scripts om de data te verzamelen.

Ik ben de afgelopen weken bezig geweest met het uitkunnen lezen van de Chint-Omvormer van mijn Zonnepanelen.
Hiervoor heb ik op internet een Python library gevonden, namelijk pv - Python-based PV Inverter Monitoring Library.

In het bestand cms.py heb ik echter een regel toegevoegd omdat ik deze miste in de output:
Orgineel

                        'Ipv3':         ('\x06',                10.0),          # PV3 Current (A)
                        'Vpv':          ('\x40',                10.0),          # PV Voltage (V)
Aangepast:
                        'Ipv3':         ('\x06',                10.0),          # PV3 Current (A)
                        'E-Today':      ('\x0D',                100.0),         # Energy to grid Today (kWh)
                        'Vpv':          ('\x40',                10.0),          # PV Voltage (V)


Ik heb dit script geplaatst op een Raspberry Pi, uitgerust met de nieuwste versie van Raspbian (Jessie), die met een USB-Serieel-kabel is aangesloten op de RS-232 poort van de omvormer.

Daarnaast heb ik een script gemaakt dat gebruik maakt van de library en gekozen data in een MySQL database plaatst.
Het script dat ik heb gemaakt is het volgende:

MySQL_Loaded=True
import sys
import datetime
import threading
import pv
import serial
#from datetime import datetime, time
from pv import cms
try:
  import mysql.connector
except ImportError:
  MySQL_Loaded=False

p1_mysql_user = 'MySQL_SMD_Gebruiker'
p1_mysql_passwd = 'MySQL_SMD_Gebruiker_wachtwoord'
p1_mysql_host = 'localhost'
p1_mysql_db = 'SMD'

def show_error():
  ft = sys.exc_info()[0]
  fv = sys.exc_info()[1]
  print("Fout type: %s" % ft)
  print("Fout waarde: %s" % fv)
  return

def db_pv_telegram():
  query = "insert into pv_log values (\'" + \
    pv_timestamp + "\',\'" + \
    pv_meter_supplier + "\',\'" + \
    pv_header + "\',\'" + \
    str(pv_equipment_id) + "\',\'" + \
    str(pv_voltage) + "\',\'" + \
    str(pv_current_power_out) + "\',\'" + \
    str(pv_current_current_out) + "\',\'" + \
    str(pv_today_power_out) + "\',\'" + \
    str(pv_meterreading_out) + "\',\'" + \
    str(pv_hours) + "\',\'" + \
    str(pv_temp) + "\',\'" + \
    str(pv_mode) + "\',\'" + \
    str(pv_error) + "\')"

#  print (query)
  try:
    db = mysql.connector.connect(user=p1_mysql_user, password=p1_mysql_passwd, host=p1_mysql_host, database=p1_mysql_db)
    c = db.cursor()
    c.execute(query)
    db.commit()
    print("PV telegram in database %s / %s gelogd op: %s" % (p1_mysql_host, p1_mysql_db, pv_timestamp) )
    db.close()
  except:
    show_error()
    print("Fout bij het openen van / schrijven naar database %s / %s. Log kwijt." % (p1_mysql_host, p1_mysql_db) )
  return

#pv.debug()
#pv.debug_color()

port = serial.Serial('/dev/ttyUSB0', timeout=5)
inv = cms.Inverter(port)

def printit():
#  print(datetime.datetime.now())
  global pv_timestamp, pv_meter_supplier, pv_header, pv_equipment_id, pv_voltage, pv_current_power_out, pv_current_current_out, pv_today_power_out
  global pv_yesterday_power_out, pv_meterreading_out, pv_hours, pv_temp, pv_mode, pv_error, pv_previous_power_out

  try:
    if pv_meter_supplier in globals():
      pv_timestamp = datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d %H:%M:%S" )
  except NameError:
    pv_timestamp = datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d %H:%M:%S" )
    pv_meter_supplier = '-'
    pv_header = '-'
    pv_equipment_id = 0
    pv_voltage = 0
    pv_current_power_out = 0
    pv_current_current_out = 0
    pv_today_power_out = 0
    pv_previous_power_out = 0
    pv_yesterday_power_out = 0
    pv_temp = 0
    pv_mode = 0
    pv_error = 0
    pv_meterreading_out = 0
    pv_hours = 0
    print ("===============================[ OPSTARTEN ]===============================")

  pv_timestamp = datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d %H:%M:%S" )

  print ("==========================[ %s ]==========================" % pv_timestamp )
  threading.Timer(10.0, printit).start()
  inv.reset()                    # Reset all communications on the serial connection
  sn = inv.discover()            # Look for connected devices
  if sn is None:
    print ("Inverter is not connected.")
    print ("pv_today_power_out     : %s" % pv_today_power_out)
    print ("pv_yesterday_power_out : %s" % pv_yesterday_power_out)
    pv_voltage = 0
    pv_current_power_out = 0
    pv_current_current_out = 0
    pv_temp = 0
    pv_mode = 0
    pv_error = 0
    now = datetime.datetime.now()
    now_time = now.time()
    if datetime.time(0,30) >= now_time >= datetime.time(0,0) and pv_yesterday_power_out == 0:
      pv_yesterday_power_out = pv_today_power_out
      pv_today_power_out = 0
    db_pv_telegram()
    return
  ok = inv.register(sn)        # Associates the inverter and assigns default address
  version =  (inv.version())
  splitted = version.split()
  count = 0
  while count <= len(splitted)-1:
    count = count + 1
  param_layout = inv.param_layout()
  parameters = inv.parameters(param_layout)
  status_layout = inv.status_layout()
  status = inv.status(status_layout)
  parameters = dict(parameters)
  status = dict(status)

  pv_meter_supplier = splitted[4]
  pv_header = version
  pv_equipment_id = splitted[5]
  pv_voltage = status['Vpv']
  pv_current_power_out = status['Pac']
  pv_current_current_out = status['Iac']
  pv_today_power_out = status['E-Today']
  pv_meterreading_out = status['E-Total']
  pv_hours = status['h-Total']
  pv_temp = status['Temp-inv']
  pv_mode = status['Mode']
  pv_error = status['Error']
  print ("[ Voor vergelijkingen: ]")
  print ("pv_today_power_out     : %s" % pv_today_power_out)
  print ("pv_previous_power_out  : %s" % pv_previous_power_out)
  print ("pv_yesterday_power_out : %s" % pv_yesterday_power_out)
  if (pv_today_power_out - pv_yesterday_power_out < 0) and (pv_today_power_out < pv_previous_power_out):
    pv_yesterday_power_out = 0
  else:
    pv_previous_power_out = pv_today_power_out
    pv_today_power_out = pv_today_power_out - pv_yesterday_power_out
  print ("[ Na vergelijkingen: ]")
  print ("pv_today_power_out     : %s" % pv_today_power_out)
  print ("pv_previous_power_out  : %s" % pv_previous_power_out)
  print ("pv_yesterday_power_out : %s" % pv_yesterday_power_out)
  db_pv_telegram()

  print ("==========================================================================================")
  return

printit()
Uiteraard zijn de database login gegevens geanonimiseerd.
In MySQL heb ik een database aangemaakt met de naam SMD, daarin heb ik een tabel aangemaakt met de naam: pv_log.
De code om de kolommen aan te maken is de volgende:
CREATE TABLE `pv_log` (
 `pv_timestamp` DATETIME NOT NULL,
 `pv_meter_supplier` TINYTEXT NULL,
 `pv_header` TINYTEXT NULL,
 `pv_equipment_id` TINYTEXT NULL,
 `pv_voltage` DECIMAL(6,3) NULL DEFAULT NULL,
 `pv_current_power_out` DECIMAL(10,3) NULL DEFAULT NULL,
 `pv_current_current_out` DECIMAL(6,3) NULL DEFAULT NULL,
 `pv_today_power_out` DECIMAL(6,3) NULL DEFAULT NULL,
 `pv_meterreading_out` DECIMAL(9,3) NULL DEFAULT NULL,
 `pv_hours` INT(11) NULL DEFAULT NULL,
 `pv_temp` DECIMAL(3,1) NULL DEFAULT NULL,
 `pv_mode` TINYINT(2) NULL DEFAULT NULL,
 `pv_error` TINYINT(3) NULL DEFAULT NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=COMPACT
;

Tevens heb ik een gebruiker aangemaakt die de rechten heeft om gegevens naar de SMD/pv_log te schrijven en te lezen. op de Raspberry Pi heb ik python, python-mysql.connector en python-serial geïnstalleerd met behulp van apt-get.

De Chint omvormer, welke trouwens gemaakt wordt door PhoenixTec en ook onder andere merken verkrijgbaar is, heeft wat toevoegingen welke best lastig zijn voor je PV_Today.
Namelijk de volgende:
  1. Na opstarten tot de eerste 0,1 kWh is opgewekt, geeft de omvormer de eindstand van gisteren weer
  2. aan het eind van de dag "stuitert" de dag-opbrengst omdat de omvormer soms niet meer reageert (uitgeschakelt is) door te weinig zonlicht.
 Beide eigenaardigheden heb ik in mijn script kunnen ondervangen, en loopt de dagopbrengst (punt 2) door tot middernacht, waarna hij op 0 gezet wordt.

Het script dat ik dit blog beschrijf is nog een test-versie en ik zal in de komende tijd herschreven worden. Maar hopelijk hebben mensen die hun omvormer uit willen lezen er al wat aan.

zaterdag 15 augustus 2015

Voorstellen

Ik zal mij even voorstellen. Ik ben Raymond.
In deze blog wil ik mijn knutsel-projecten gaan verslaan.

Thinkering


Knutselen betekent in het Engels "tinkering", wat een stuk beter klinkt in mijn oren, knutselen klinkt mij te simpel, thinkering klinkt meer als iets waar je over na hebt gedacht.

Hierbij ook nog even de vertaling zoals ik die vond op het internet:
  1. tinkering:
    • knutselen ; knutselwerk ; geknutsel ; knutselarij ; gebroddel ; geklungel
  2. tinker:
    • knutselen ; sleutelen ; fröbelen ; prutsen ; verwarren ; haspelen ; tot een warboel maken ; verprutsen ; aanmodderen ; rommelen 
Verwarren, tot een warboel maken, verprutsen, aanmodderen, zijn nou toch niet echt woorden waar ik mijn projecten mee wil omschrijven (althans dat is mijn bedoeling).

Projecten


Mijn projecten hebben voornamelijk tot doel het dagelijks leven te veraangenamen.

Projecten die ik in het verleden al heb gemaakt zijn onder andere:

Barbecue: De slagerbarbecue (zo'n een rechthoekige bak met rooster) aangepast zodat het rooster nu op 3 niveaus kan hangen.
Eettafel: Van de Ikea eettafel Norden die wij thuis hebben, heb ik de poten ingekort en er zwenkwielen onder gemonteerd, zodat hij makkelijk aan de kant gezet kan worden.
Carcassonne-kist: Ik ben een groot bord-spellen-fanaat, dus heb ik voor mijn Carcassonne-verzameling een mooie opbergkist gemaakt

Programmeren 


Programmeren doe ik graag voor de Arduino, de Raspberry Pi, de Pebble of een pc. De besturingssystemen waaronder ik programmeer zijn Linux (Debian, Mint of Raspbian) of Windows.

De talen waarin ik de meeste programma's schrijf zijn C (Arduino, Pebble), Pascal (Delphi/Lazarus), Python, PHP, Javascript (Pebble.js).

North Central Positronics, LTD.


Waarom North Central Positronics, LTD. als Blog-naam?
Naast bord-spellen-fanaat lees ik ook graag, vooral Stephen King.
Stephen King heeft een (nu) 8-delig verhaal geschreven genaamd De Donkere Toren, wat hijzelf lang zag als zijn levenswerk, de meeste van zijn andere verhalen zijn op de een of andere manier ook aan dit verhaal gekoppeld.

In de Donkere Toren staat op technische apparatuur altijd weer de naam North Central Positronics, LTD. voor en ik vond dit een mooie toepasselijke naam voor mijn blog omdat die ook voornamelijk om techniek draait.

De Donkere Toren speelt om een constructie die zich in het hart van het multiversum bevindt. (meer info over het verhaal lees je op Wikipedia).

Ik ben woonachtig in Utrecht en laatst vond ik (via de Stephen King Fanclub Nederland) een mooi plaatje van een verwilderde Dom-toren, zodat het net lijkt op wat Stephen King omschrijft als de Donkere Toren, vandaar dat deze ook als achtergrond op mijn blog staat.