• Benvenuti su RaspberryItaly!
Benvenuto ospite! Login Login con Facebook Registrati Login with Facebook


Valutazione discussione:
  • 0 voto(i) - 0 media
  • 1
  • 2
  • 3
  • 4
  • 5

[-]
Tags
python salvataggio con dati e monitoraggio

Monitoraggio e salvataggio dati con python
#1
Salve a tutti.
In questi ultimi giorni ho installato un sistema di monitoraggio dell'illuminamento solare sul tetto di casa, tramite sensore di luce BH1750, collegato ad arduino, opportunamente programmato con sketch realizzato da altri (non sono un programmatore putroppo). L'arduino, a sua volta, è collegato ad un raspberry pi 3 B ver. 1.2, con raspbian strech lite. Tramite file python riesco ad importare i valori di illuminamento solare su terminale, ma, dopo numerosi tentetivi, non sono riuscito a salvare i dati su un file txt, che mi serve per riportarli sul software di monitoraggio metern.
Ricapitolando:

Sensore solare = Arduino Uno = Raspberry PI 3 B = File Python per lettura valori di lux su terminale e salvataggio dati in file txt = MeterN per il monitoraggio dell'illuminamento solare

Spero di essere stato chiaro e mi scuso per la mia scarsa conoscenza dei linguaggi di programmazione.
Grazie per i vostri eventuali aiuti e suggerimenti.
Buona vita.
Risposta
#2
Chiaro sei stato chiaro, ma dicci un po' come lavora il tuo file python, il valore è in una variabile immagino. E come deve essere il file txt risultante? Tipo timestamp, valore? E ogni quanto tempo?

Inviato dal mio A0001 utilizzando Tapatalk
Risposta
#3
Innanzi tutto grazie Zzed.
Sono partito con questo file python bh1750.py, il cui codice (incompleto) è

Codice:
import serial
arduinoSerialData = serial.Serial('/dev/ttyUSB0',9600)
file = '/dev/shm/luxlight.txt'
while  True:
     myData = arduinoSerialData.readline()
     print myData
fp = open(file,'w')
fp.close()

So che manca qualcosa, ma non ho capito cosa, perchè il file non viene creato.
Nel file txt dovrebbe essere memorizzato il valore in tempo reale del'illuminamento solare (lux) ed eventualmente anche il valore corrispondente della potenza (W/m2), ottenuto dividendo il valore di cui sopra per 683. Nelle varie prove che ho già fatto non ho ottenuto niente di buono. Sto cercando di imparare un minimo di programmazione, ma per adesso, se posso, chiede lumi a chi ne sa più di me.
Grazie.


Allegati Anteprime
   
Risposta
#4
Nell'esempio di codice postato, nel ciclo while, apri un file (file) in scrittura ('w') e poi lo richiudi senza aver eseguito altra operazione.
Per poter scrivere qualcosa: fp.write(myData) tra fp=open.... e fp.close()
Risposta
#5
esatto.

L'ultima parte andrebbe modificata in
Codice:
fp = open('file.txt','a')   # a cioè append    aggiunge qualcosa al file
fp.write(myData, (myData\683))
fp.close()

puoi aggiungere data e ora, importando datetime all' inizio
Codice:
import datetime
e mettendo data e ora accanto a ogni dato..

tipo
t = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S")
Codice:
fp = open('file.txt','a')   # a cioè Append = aggiunge qualcosa al file senza sovrascriverlo
t = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S")  # prende data e ora correnti
fp.write(t, myData, (myData\683)+ "\n")  # scrive data e ora, il valore, il diviso 683 e va a capo
fp.close()
Risposta
#6
Vado un passo alla volta per imparare.
Più che la data e l'ora mi serve rilevare il tempo tra un dato e l'altro, per calcolare l'energia al metro quadro. Questo è il codice :
Codice:
import serial
import time
arduinoSerialData = serial.Serial('/dev/ttyUSB0',9600)
file = '/dev/shm/luxlight.txt'
fold = open('/dev/shm/consumi1.txt','r')
while  True:
     myData = arduinoSerialData.readline()
     tmyData0 =0
     tmyData1 = time.time()
     deltat = tmyData1 -  tmyData0
     fp = open(file,'a')
     fp = (myData, (myData*deltat)) +'*Wh\m2\n'
     fp = (myData, (myData*0.00146412884333821)) +'*W\m2)\n'
     fp.close()
Sicuramente ci sono una valanga di errori. In tal caso vi chiedo di avere pazienza, ma come ho già avuto modo di dire, non sono esperto di programmazione.
Risposta
#7
Thumbs Down 
Salve a tutti.
Sono riuscito ad importare i dati da arduino su raspberri con questo file python:
Codice:
import serial
import time
arduinoSerialData = serial.Serial('/dev/ttyUSB1',9600)
metern_id = 7
file = '/dev/shm/metern'+str(metern_id)+'.txt'
while True:
 myData = arduinoSerialData.readline()
luce = str(metern_id) + '(' + str(myData) + '*lux)\n'
 fp = open(file,'w')
 fp.write(luce)
 fp.close()
Quello che ottengo nel file metern7.txt è ciò che si vede nell'immagine allegata:


7(14.84
*lux) sbagliato

invece di

7(14.84*lux) corretto


Nella dashboard di metern mi viene fuori un errore che mi blocca il programma.
Se correggo manualmente l'errore sulla dashboard di metern mi appare il valore corretto.
C'è qualcuno che può cortesemente aiutarmi/consigliarmi su come correggere questo errore?
Grazie. Buona vita.


Allegati Anteprime
           
Risposta
#8
Ciao, non avendo il tuo sistema, non sono in grado di riprodurre il problema.
assegnando una variabile a myData, il tutto funziona correttamente. Possibile che nella stringa della seriale ricevuta con arduino vi sia già un \n che manda a capo?
Risposta
#9
Ciao Zzed.
Anche io ho pensato ad una cosa simile, ma non essendo un programmatore, non sono in grado di individuare se c'è questo comando di andare a capo. In ogni caso, lo sketch caricato su arduino è questo:
Codice:
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>

// The I2C address is 0x23 (ADDR pin is low) or 0x5C (ADDR pin is high).
#define BH1750_I2C_ADDRESS_1        0x23
#define BH1750_I2C_ADDRESS_2        0x5C

#define BH1750_POWER_DOWN           0x00    // Stop all operations
#define BH1750_POWER_ON             0x01    // Power on and wait for measurement command
#define BH1750_RESET                0x07    // Clears the illuminance data register, does not work in power down.
#define BH1750_CONT_H_RES_MODE      0x10
#define BH1750_CONT_H_RES_MODE2     0x11
#define BH1750_CONT_L_RES_MODE      0x13
#define BH1750_ONE_TIME_H_RES_MODE  0x20
#define BH1750_ONE_TIME_H_RES_MODE2 0x21
#define BH1750_ONE_TIME_L_RES_MODE  0x23
#define BH1750_MEAS_TIME_H          0x40
#define BH1750_MEAS_TIME_L          0x60


// Moving average array.
// A "moving average" is also called "rolling average" or "running average".
#define NUM_SAMPLES_AVG   10
float moving_avg[NUM_SAMPLES_AVG];
int index_avg;


const int _i2c_address = BH1750_I2C_ADDRESS_1;


// The default correction factor to calculate the lux is 1.2.
// Adjust it when you are able to calibrate the BH1750.
// According to the datasheet, the value can be 0.96 to 1.44.
// It is not know if this correction factor is the same for the whole range.
const float BH1750_factor = 1.2;


void setup()
{
 Serial.begin( 9600);
 // Serial.println(F( "\nBH1750 lux sensor"));

 Wire.begin();

 // Start the sensor and test if the I2C address is right.
 int error = BH1750_begin();
 if( error != 0)
 // Serial.println(F( "Error, BH1750 not found"));

 // Initialize the moving average array.
 for( int i=0; i<NUM_SAMPLES_AVG; i++)
 {
   moving_avg[i] = 0.0;                        // or fill it with the actual current lux value.
 }
 index_avg = 0;
}


void loop()
{
 // Serial.println(F( "------------------"));


 // ----------------------------------------
 // Low Resolution
 // ----------------------------------------
 // Low resolution could be a quick check of the light intensity.
 // It could be used to determine which high resolution mode will be used.
 write8( BH1750_POWER_ON);
 write8( mt_H( 69));             // default
 write8( mt_L( 69));             // default
 write8( BH1750_ONE_TIME_L_RES_MODE);
 delay( 24);    // typical 16ms, maximum 24ms
 uint16_t x = read16();
 // Divide the result by a factor of 1.2 (default value)
 // The resulting lux is calculated with float numbers.
 float lux_lowres = (float) x / BH1750_factor;        // BH1750_factor is usually 1.2
 // Serial.print(F( "low res   : "));
 // Serial.println( lux_lowres);


 // ----------------------------------------
 // High Resolution
 // ----------------------------------------
 // Normal request of the lux in one time high resolution mode.
 write8( BH1750_POWER_ON);
 write8( mt_H( 69));             // default
 write8( mt_L( 69));             // default
 write8( BH1750_ONE_TIME_H_RES_MODE);
 delay( 180);    // typical 120ms, maximum 180ms
 uint16_t a = read16();
 // Divide the result by a factor of 1.2 (default value)
 // The resulting lux is calculated with float numbers.
 float lux = (float) a / BH1750_factor;              // BH1750_factor is usually 1.2
 // Serial.print(F( "high res  : "));
 // Serial.println( lux);


 // ----------------------------------------
 // High Resolution Mode2 with maximum measurement time
 // ----------------------------------------
 // Extra sensitive 0.11 lux resolution.
 // The MTregister is default 69.
 // It can be minimal 31 and maximum 254
 write8( BH1750_POWER_ON);
 write8( mt_H( 254));          // maximum value of measurement time
 write8( mt_L( 254));
 write8( BH1750_ONE_TIME_H_RES_MODE2);
 delay( 662);           // 180 * 254 / 69
 uint16_t b = read16();
 float lux_dark = (float) b / BH1750_factor * ( 69.0 / 254.0 ) / 2.0;      // BH1750_factor is usually 1.2
 // Serial.print(F( "0.11 res  : "));
 // Serial.println( lux_dark);


 // ----------------------------------------
 // High resultion with minimum measurement time
 // ----------------------------------------
 // Extra range for bright light up to 100000 lux
 // The calculation could result into a lux value up to 120 klx (120000 lux).
 // Normal High Resolution mode, with minimal time measurement (31 is minimum for MTregister).
 write8( BH1750_POWER_ON);
 write8( mt_H( 31));          // lowest value of measurement time
 write8( mt_L( 31));
 write8( BH1750_ONE_TIME_H_RES_MODE);
 delay( 81);            // 180 * 31 / 69
 uint16_t c = read16();
 float lux_light = (float) c / BH1750_factor * ( 69.0 / 31.0 );       // BH1750_factor is usually 1.2
 // Serial.print(F( "100k range: "));
 Serial.println( lux_light);


 // ----------------------------------------
 // moving average
 // ----------------------------------------
 moving_avg[index_avg] = lux_dark;

 // Calculate the average.
 float total_avg = 0.0;
 for( int i=0; i<NUM_SAMPLES_AVG; i++)
 {
   total_avg += moving_avg[i];
 }
 total_avg /= (float) NUM_SAMPLES_AVG;
 // Serial.print(F( "average   : "));
 // Serial.println( total_avg);

 // advance index for the moving average array.
 index_avg++;
 if( index_avg >= NUM_SAMPLES_AVG)
   index_avg = 0;


 delay( 1000);
}


int BH1750_begin()
{
 // Send command 'RESET' for extra safety.
 // A 'RESET' is only valid with power on.
 // A 'RESET' only resets the illuminace data register.
 //
 // Three checks if the communication with the sensor is okay.
 // No more error checks after this.

 int error = 0;
 
 error = write8( BH1750_POWER_ON);
 if( error != 0)
   return( error);
   
 error = write8( BH1750_RESET);
 if( error != 0)
   return( error);

 error = write8( BH1750_POWER_DOWN);
 if( error != 0)
   return( error);

 return( error);  
}


inline uint8_t mt_H( uint8_t mt)
{
 return( BH1750_MEAS_TIME_H | (mt >> 5));  // highest 3 bits
}

inline uint8_t mt_L( uint8_t mt)
{
 return( BH1750_MEAS_TIME_L | (mt & 0x1F));   // lowest 5 bits
}


// Read the two bytes from the BH1750
// If an error occurs, then zero is returned.
uint16_t read16()
{
 uint16_t x;
 int n = Wire.requestFrom( _i2c_address, 2);
 if( n == 2)
 {
   byte highbyte = Wire.read();              // highest byte first
   byte lowbyte  = Wire.read();
   x = word( highbyte, lowbyte);
 }
 else
 {
   x = 0;
 //  Serial.println("ERROR I2C fail 1");          // for debugging
 }
 return( x);
}


// Write the command byte to the BH1750
// An error is returned, it is zero for no error.
int write8( uint8_t command)
{
 Wire.beginTransmission( _i2c_address);
 Wire.write( command);
 int error = Wire.endTransmission();

 if( error != 0)                               // for debugging
//   Serial.println("ERROR I2C fail 2");         // for debugging
 
 return( error);
}
Grazie per la tua attenzione.
Risposta
#10
Nello sketch non vi è alcuna istruzione di accodamento di un "new line" (\n) ad alcuna stringa/variabile. Da alcuni post letti in rete in riferimento all'istruzione "SerialData.readline()" il new line viene aggiunto da libreria per indicare la fine del messaggio. Il reale messaggio è quindi composto da n-1 byte (o caratteri); dovresti copiare/scansionare il messaggio sino a n-1 byte, copiandolo eventualmente in un'altra stringa o array .
Risposta
  


Vai al forum:


Navigazione: 4 Ospite(i)
Forum con nuovi Post
Forum senza nuovi post
Forum bloccato
Forum Redirect