Ładowanie…

Moja autostrada wiedzy

jedziesz ze mną?
Zacznij eksplorować

Projekt PiMP – logowanie danych

W poprzednim artykule udało nam się zmusić Pico do odczytu i wyświetlenia danych na wyświetlaczu OLED, w tej części będziemy starali się utworzyć odpowiedni plik o konkretnej strukturze do którego zapisywane będą odczyty z sensora, a on sam zapisywany będzie na pamięci Flash kontrolera.

Efektem tego była kolejna modyfikacja kodu programu :

from machine import Pin, I2C        
import time
year, month, day, hour, mins, secs, weekday, yearday = time.localtime()
from time import sleep
import bme280        
from ssd1306 import SSD1306_I2C

builtin_led = Pin(25, Pin.OUT)

i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)    
oled = SSD1306_I2C(128, 64, i2c)
datka = ("{}-{:02d}-{:02d}".format(year, month, day))
godzina = ("{}:{:02d}:{:02d}".format(hour, mins, secs))
znak = ('_')
#sekcja tworzenia pliku z logiem 
#file=open("data.txt","w")
filename = (datka + znak + godzina)
file=open(filename + '.txt', 'w')

while True:
  builtin_led.value(1)
  oled.fill(0)
  bme = bme280.BME280(i2c=i2c)        
  temperature = bme.values[0]         
  pressure = bme.values[1]            
  humidity = bme.values[2]            
  
  
  print("{}-{:02d}-{:02d}".format(year, month, day))
  print("{}:{:02d}:{:02d}".format(hour, mins, secs))
  print('Temperatura: ', temperature)    
  print('Wilgotnosc: ', humidity)
  print('Cisnienie: ', pressure)
  
  file.write(str(datka)+",")
  file.write(str(godzina)+",")
  file.write(str(temperature)+",")
  file.write(str(pressure)+",")
  file.write(str(humidity)+"\n")
 
  
  oled.text(""+datka, 25, 0)
  oled.text(""+godzina, 30, 10)
  oled.text("Temp "+temperature, 15, 20)
  oled.text("Cis "+pressure, 15, 30)
  oled.text("Wilg "+humidity, 15,40)
  oled.show()                          #wyswietlenie na wyswietlaczu
  sleep(10)     #przerwa 10 w petli

Wszystko byłoby okej z kodem powyżej gdyby nie to, że zegar jak już wcześniej pisałem nie pobiera poprawnych danych i nie potrafi zapisać odpowiedniego pliku z konkretną nazwą.

Na szczęście w moich rękach jest już Pico „W” z interfejsem sieciowym. Pierwsze testy połączenia zakończyły się sukcesem, uruchomienie programu zawierające zmienne czasu także zakończyło się sukcesem. Kod pozwalający na takie bajery przedstawia się mniej więcej tak :

from machine import Pin, I2C        
import time
year, month, day, hour, mins, secs, weekday, yearday = time.localtime()
from time import sleep
import bme280        
from ssd1306 import SSD1306_I2C
import network

builtin_led = Pin(25, Pin.OUT)

i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)    
oled = SSD1306_I2C(128, 64, i2c)

wlan = network.WLAN(network.STA_IF)
wlan.active(True)

ssid = "nazwa_sieci"
pw = "hasło_sieci"

wlan.connect(ssid, pw)

def light_onboard_led():
    led = machine.Pin('LED', machine.Pin.OUT)
    led.on();

timeout = 10
while timeout > 0:
    if wlan.status() >= 3:
        light_onboard_led()
        break
    timeout -= 1
    print('Waiting for connection...')
    time.sleep(1)
   
wlan_status = wlan.status()

while True:
  oled.fill(0)
  bme = bme280.BME280(i2c=i2c)        
  temperature = bme.values[0]         
  pressure = bme.values[1]            
  humidity = bme.values[2]            
  data = ("{}-{:02d}-{:02d}".format(year, month, day))
  godzina = ("{}:{:02d}:{:02d}".format(hour, mins, secs))
  
  print("{}-{:02d}-{:02d}".format(year, month, day))
  print("{}:{:02d}:{:02d}".format(hour, mins, secs))
  print('Temperatura: ', temperature)    
  print('Wilgotnosc: ', humidity)
  print('Cisnienie: ', pressure)
  
  oled.text(""+data, 25, 0)
  oled.text(""+godzina, 30, 10)
  oled.text("Temp "+temperature, 15, 20)
  oled.text("Cis "+pressure, 15, 30)
  oled.text("Wilg "+humidity, 15,40)
  oled.show()                          #wyswietlenie na wyswietlaczu
  sleep(10)     #przerwa 10 w petli
 

No i w pizdu !

Minęły chyba dwa dni od momentu kiedy napisałem wcześniejszą część tego artykułu i zabrałem się za pisanie tego co widzicie poniżej w kolejny nagłówku, no i przy przyjemnym kontemplowaniu innego problemu który pojawił się podczas pisania zauważyłem że co prawda rozwiązałem problem z datą i godziną na wyświetlaczu, w konsoli oraz tym co wpisuje się do pliku ALE cały czas mam datę pobraną w momencie uruchamiania programu. Data nie odświeżała się wcale a jest to w gruncie rzeczy dość istotny element całego systemu 🙂 Lamer jak widać w pełnej krasie. Więc przy okazji zmiany całej tej pętli zabrałem się za modyfikowanie kwestii pobierania daty i godziny. Celem modyfikacji było zabezpieczenie sytuacji w której urządzenie nie połączy się z Internetem aby było w tym momencie w stanie użyć jakiegoś zegara RTC. Owocem była absolutna zmiana działania programu. Poniżej przedstawiam wygląd kodu programu głównego oznaczonego wydawczo na wersję 0.4.4:

# PiMP ver 0.4.4 
# by Slawek 'chinczyk' Meredyk

import network, urequests, utime, machine, time
from machine import RTC, I2C, Pin
from ssd1306 import SSD1306_I2C
import bme280
from time import sleep

# ustawienia
seryjny= "100" # numer rozpoznawania urzadzenia unikalny dla kazdej sztuki
znak="_"
znakczasu=str(time.ticks_ms())
ssid = "" # nazwa sieci ( w przyszlosci w innym pliku )
pw = "" # haslo ( w przyszlosci w innym pliku )
url = "http://worldtimeapi.org/api/timezone/Europe/Warsaw" # jak by co wszystkie strefy tu http://worldtimeapi.org/timezones
web_query_delay = 50000 # interwal zapytania strony o jsona
retry_delay = 4000 # interwal zapytania w razie bledu zapytania
filename = (seryjny + znak + znakczasu) #utworzenie nazwy pliku skladajacego sie z numeru seryjnego i czasu w formatowaniu milisekend 

i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)    
# malowanie wyswietlacza wynikiem łączenia do wifi 
print("Laczenie do wifi...")
oled = SSD1306_I2C(128, 64, i2c)
oled.fill(0)
oled.text("Laczenie", 0, 5)
oled.text(" do wifi...", 0, 15)
oled.show()

# wywolanie wewnetrznego RTC
rtc = RTC()

# Proba polaczenia wifi
wifi = network.WLAN(network.STA_IF) # station mode
wifi.active(True)
wifi.connect(ssid, pw)

# czekaj na polaczenie
while not wifi.isconnected():
    pass

# wifi polaczone
print("IP:", wifi.ifconfig()[0], "\n")
oled.text("Polaczono. IP: ", 0, 35)
oled.text(" " + str(wifi.ifconfig()[0]), 0, 45)
oled.show()
sleep(2)

# ustaw timer
update_time = utime.ticks_ms() - web_query_delay

# Petla wlasciwa
while True:
    
    # jesli zgubisz polaczenie zrob reboot ( nie wiem czy to dobre wyjdzie w testach )
    if not wifi.isconnected():
        machine.reset()
    
    # query i dzejson z http 
    if utime.ticks_ms() - update_time >= web_query_delay:
    
        #Pobieram dane HTTP 
        response = urequests.get(url)
        
        if response.status_code == 200: # query success
                    
            # parasuje JSON
            parsed = response.json()
            datetime_str = str(parsed["datetime"])
            year = int(datetime_str[0:4])
            month = int(datetime_str[5:7])
            day = int(datetime_str[8:10])
            hour = int(datetime_str[11:13])
            minute = int(datetime_str[14:16])
            second = int(datetime_str[17:19])
            subsecond = int(round(int(datetime_str[20:26]) / 10000))
            
            
            # updejt wewnetrznego rtc
            rtc.datetime((year, month, day, 0, hour, minute, second, subsecond))
            update_time = utime.ticks_ms()
            
            # generowanie poprawnego formatu daty 
            date_str = "{1:02d}/{2:02d}/{0:4d}".format(*rtc.datetime())
            time_str = "{4:02d}:{5:02d}:{6:02d}".format(*rtc.datetime())
            
            #odczyt z czujnikow
            bme = bme280.BME280(i2c=i2c)        
            temperature = bme.values[0]         
            pressure = bme.values[1]            
            humidity = bme.values[2]
            file=open(filename + '.txt', 'a')
            
            print('Data',date_str)
            print('Czas',time_str)
            print('Temperatura: ', temperature)    
            print('Wilgotnosc: ', humidity)
            print('Cisnienie: ', pressure)
            
            # dopisywanie pliku
            file.write(str(date_str)+",")
            file.write(str(time_str)+",")
            file.write(str(temperature)+",")
            file.write(str(pressure)+",")
            file.write(str(humidity)+"\n")
            file.close()
   
        else: # jesli query nie zadziaialo proboj jeszcze raz
            update_time = utime.ticks_ms() - web_query_delay + retry_delay
            

    # malowanie wyswietlacza
    oled.fill(0)
    oled.text(date_str,10, 0)
    oled.text(time_str,10, 10)
    oled.text("Temp "+temperature, 10, 20)
    oled.text("Cis "+pressure, 10, 30)
    oled.text("Wilg "+humidity, 10,40)          
    oled.show()
    utime.sleep(1)

Tym razem przyjąłem już też zmiany rozwojowe takie jak dodanie zmiennej numeru seryjnego, który w przyszłości będzie identyfikatorem danej sztuki urządzenia w bazie danych i cloudzie do kolektowania i wyświetlania informacji z PiMP’s. Teraz czekamy tylko na GPS ponieważ pierwszy który przyjechał wydaje się nie działać poprawnie, więc aby się upewnić zakupiłem jeszcze jedną sztukę.

Budowa strony powitalnej w html i hotspot

Najprościej powiedzieć iż aby być dojść do hotspota trzeba hotspota 🙂

Zamysł konfiguracyjny jest taki że dostając do ręki gotowe urządzenie end user ma wykonać jak najmniej czynności prowadzących do poprawnego działania urządzenia. Inaczej mówiąc (trochę kolokwialnie) ma być idioto-odporne. Idąc tym tokiem rozumowania zacząłem budować pierwszy program który uruchomi się zaraz po starcie urządzenia ma on za zadanie z Pico zrobić hotspota o nazwie sieci PiMP + nr seryjny urządzenia i haśle podanym w dokumentacji.

Nowy użytkownik po połączeniu się do wyżej podanej sieci dostaje informacyjna stronę www na której musi wykonać akcję mającą na celu wypełnienie formularza w którym znajduje się nazwa sieci oraz hasło do telefonicznego hotspota. Połączenie to zasilać będzie urządzenie PiMP w internet, a to pozwoli na wymianę informacji między serwerem a urządzeniem.

Kolejnym etapem po zapisaniu danych w formularzu jest zapisanie danych za pomocą micropythona do osobnego pliku o nazwie dupa.py z którego będzie korzystał już program właściwy. Dalej będzie restart urządzenie i podłączenie się do właściwego hotspota telefonicznego.

I wszystko na tym etapie byłoby proste, łatwe i klarowne jak by nie fakt że formularz jest w HTML a zazwyczaj wykonanie posta czyli wysłanie danych z formularza gdzieś odbywa się w dzisiejszych czasach w PHP. Jak wiecie PHP działa po stronie serwera a nie jak HTML po stronie przeglądarki więc każdy Sherlock wykminił właśnie że PHP na Pico nie zadziała i tu dla mnie zaczęły się schody. Długo szukałem sposobu aby dane z formularza w HTML przekazać do Pythona i nim zbudować potrzebny plik.

Konkluzje po kolejnym etapie

Po rozmowach z kolegą odnośnie materiału obudowy oraz niej samej są nowe wnioski :

  • kolor filamentu musi być najlepiej biały z powodu absorbowania światła słonecznego.
  • obudowa musi być podzielona na dwie komory jedna będzie „hermetyczna” a druga musi być wentylowana aby zapewnić odpowiedni dopływ powietrza do badania.
  • musi powstać plik z ustawieniami urządzenia, np numer seryjny , nick osoby używające, link do wysyłania danych. ( i tu już po części mamy takie ustawienia w głównej części programu, w przyszłości pomyślimy czy zrobić faktycznie dla nich odrębny plik czy budować sekcję w pliku głównym.