Lo spettro di riflettanza e' stato ottenuto dividendo il valore calibrato della foglia per il valore calibrato nel corrispondente canale dello spectralon
Primi approcci per vedere se il sensore multispettrale e' affidabile per l'uso multispettrale
In questo prova e' stata verificata la ripetibilita' nel tempo delle misure ponendo il sensore su uno spectralon ed effettuando 350 misure di bianco (il supporto del sensore e' stato ripreso da qui https://github.com/Scottapotamas/AS7265x-triad-ui/tree/master/mechanical)
Lo script per la misura ha previsto il massimo tempo di integrazione (con valori bassi in IR praticamente non c'era segnale)
L'errore per ogni canale e' stato stimato prendendo la standard deviation e dividendo per la media
A
0.44%
B
0.49%
C
0.25%
D
0.34%
E
0.05%
F
0.05%
G
0.07%
H
0.07%
R
0.10%
I
0.07%
S
0.09%
J
0.08%
T
0.13%
U
0.00%
V
0.37%
W
0.74%
K
1.55%
L
0.56%
Come si deve l'errore e' piuttosto vario tra i vari canali
Plottando la misura di ogni canale nel tempo si osserva una chiara deriva per ogni canale con in alcuni casi l'accenno di un valore asintotivo mentre in altri no
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferimento e' il seguente https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display (oppure https://github.com/hexeguitar/ESP32_TFT_PIO)
Si puo' usare tramite Arduino Ide importando le due librerie TFT_eSPI and XPT2046_Touchscreen
Iniziando dallo schermo TFT prima di provare gli esempi della libreria si deve modificare il file User_Setup.h nel folder in Arduino/libraries/TFT_eSPI
Per provare la sola componente TouchScreen si puo' usare il seguente esempio (quello di default non funziona perche' non sono mappati in modo corretto i pin)
if (touchscreen.tirqTouched() && touchscreen.touched()) {
// Get Touchscreen points
TS_Point p = touchscreen.getPoint();
// Calibrate Touchscreen points with map function to the correct width and height
x = map(p.x, 200, 3700, 1, 320);
y = map(p.y, 240, 3800, 1, 240);
z = p.z;
printTouchToSerial(x, y, z);
}
}
Il led RGB e' controllabile tramite questo script
#definePIN_RED4 // GPIO23
#definePIN_GREEN16 // GPIO22
#definePIN_BLUE17 // GPIO21
voidsetup() {
pinMode(PIN_RED, OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
pinMode(PIN_BLUE, OUTPUT);
}
voidloop() {
// color code #00C9CC (R = 0, G = 201, B = 204)
setColor(0, 201, 204);
delay(1000); // keep the color 1 second
// color code #F7788A (R = 247, G = 120, B = 138)
setColor(247, 120, 138);
delay(1000); // keep the color 1 second
// color code #34A853 (R = 52, G = 168, B = 83)
setColor(52, 168, 83);
delay(1000); // keep the color 1 second
}
voidsetColor(int R, int G, int B) {
analogWrite(PIN_RED, R);
analogWrite(PIN_GREEN, G);
analogWrite(PIN_BLUE, B);
}
Attaccando uno speaker esterno si puo' generare un suono utilizzando un altoparlante esterno collegando ai pin che sono predisposti sul DAC 2 (GPIO 26)
#defineDAC_CH226
voidsetup() {
}
voidloop() {
for (int deg = 0; deg < 360; deg = deg + 1) {
dacWrite(DAC_CH2, int(128 + 64 * sin(deg * PI / 180)));
}
}
Per usare LVGL ho provato a passare da Arduino IDE ma ho trovato un mondo di problemi. La soluzione piu' semplice e' il progetto PlatformIO (sempre con base codice Arduino)
in seguito si toglie il commento in platformio.ini in corrispondenza della propria scheda (ci sono molti modelli con differenti risoluzione e touch sia capacitivi che resistivi) e si fa il build
[platformio]
#default_envs = esp32-1732S019C
#default_envs = esp32-1732S019N
#default_envs = esp32-2424S012C
#default_envs = esp32-2424S012N
#default_envs = esp32-2432S022N
#default_envs = esp32-2432S022C
#default_envs = esp32-2432S024C
#default_envs = esp32-2432S024N
#default_envs = esp32-2432S024R
default_envs = esp32-2432S028R
#default_envs = esp32-2432S028Rv2
#default_envs = esp32-2432S028Rv3
Per personalizzare l'interfaccia grafica non sono riuscito ad importare il progetto dentro SquareLine Studio, un programma per creare interfacce di LVGL (il programma non e'stabile in nessuna delle versioni ed ha la necessita' di funzionare con sudo sotto Linux per non meglio chiariti motivi)
Per aggirare il problema ho creato un progetto ex novo Arduino in SquareLine
impostante le dimesioni dello schermo a 320x240x16 colori e nominando la prima finestra scrMain
Dopo aver testato l'interfaccia ho esportato la UI ho copiato il folder /scr/ui nel folder ui di esp32-smartdisplay-demo
Avevo la necessita' di collegare una Arduino Nano 33 BLE ad internet ma non avevo molte idee quando ho pensato di usare come ponte un telefono Android
La Arduino e' contenuta nella scatolina bianca
Per leggere i dati della porta seriale di Arduino ho collegato un cavo OTG alla USB di Android usando la libreria https://github.com/felHR85/UsbSerial. I dati poi sono stati inviati in HTTP Get tramite OKHttp. Il progetto della applicazione Android si trova sul mio GitHub https://github.com/c1p81/Seriale (si tratta di una modifica dell'esempio della libreria UsbSerial)
Questo e' invece lo skecth Arduino
========================================================= #include <Arduino_LSM9DS1.h> #include <Arduino_HTS221.h> #include <Arduino_LPS22HB.h> #include <Arduino_APDS9960.h> int conteggio; void setup() { conteggio = 0; Serial.begin(9600); while (!Serial); if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); while (1); } if (!HTS.begin()) { Serial.println("Failed to initialize humidity temperature sensor!"); while (1); } if (!BARO.begin()) { Serial.println("Failed to initialize pressure sensor!"); while (1); } if (!APDS.begin()) { Serial.println("Error initializing APDS9960 sensor."); } } void loop() { float x, y, z; double dx,dy,dz; double mx,my,mz; double fx,fy,fz; double pitch,roll = 0.0; double mpitch,mroll = 0.0; const float alpha = 0.5; float pressure = BARO.readPressure(); float temperature = HTS.readTemperature(); float humidity = HTS.readHumidity(); while (! APDS.colorAvailable()) { delay(5); } int r, g, b, light_int; APDS.readColor(r, g, b, light_int); if (IMU.accelerationAvailable()) { IMU.readAcceleration(x, y, z); dx = (double)x; dy = (double)y; dz = (double)z; mx = mx + dx; my = mx + dy; mz = mx + dz; fx = (dx*alpha) + (fx*(1-alpha)); fy = (dy*alpha) + (fy*(1-alpha)); fz = (dz*alpha) + (fz*(1-alpha)); conteggio++; } if (conteggio > 10000) { mx = mx /conteggio; my = my /conteggio; mz = mz /conteggio; roll = atan2(fy,fz)*57.29577; pitch = atan2(-fx,sqrt((fy*fy)+(fz*fz)))*57.29577; mroll = atan2(my,mz)*57.29577; mpitch = atan2(-mx,sqrt((my*my)+(mz*mz)))*57.29577; Serial.println(String(mpitch)+";"+String(mroll)+";"+String(pitch)+";"+String(roll)+";"+String(temperature)+";"+String(humidity)+";"+String(pressure)+";"+String(light_int)); conteggio = 0; fx = fy = fz = 0; mx = my = mz = 0; } delay(10); //delay(5000); }
A questo link e' comparso un interessante esempio su come utilizzare i sensori (accelerometro e giroscopio) di una Arduino BLE per addestrare una rete neurale con Tensorflow Lite e poi utilizzare la stessa libreria per classificare le gesture sempre tramite Arduino
Per prova ho inserito la Arduino sotto ad un guanto (per tenerla bloccata) e poi registrando un centinaio di rotazione del polso verso l'interno e verso l'esterno
L'ultima modifica che ho apportato e' di modificare a 50 il numero di campioni per gesture
Una volta salvata due file csv (uno per movimento) ho utilizzato questo Colab per creare il file model. h
Grafico accelerazione di riferimento
Come si deve dai grafici l'errore del modello in train/validation e' estremamente ridotto
Grafico giroscopi di riferimento
Training and validation loss
Stesso grafico precedente eliminando i primi 100 dati
Risultati validazione
Il risultato del Notebook sono un file di modello di Tensorflow Lite ed un file model.h che deve essere copiato nello sketch ImuClassifier per fare il deploy del modello
Devo ammettere che il sistema funziona ma e' lontano dall'essere perfetto. Devo ancora capire se e' un problema di posizionamento del sensore durante le varie proprie (che per ovvi motivi non e' sempre identico) od un addestramento errato
Dopo il precedente tentativo di leggere una caratteristica BLE da Python adesso un tentativo di scrivere una caratteristica (lo so e' una brutta traduzione) da Android su un dispositivo BLE
Lo sketch Arduino e' stato modificato per esporre una caratteristica 2A30 in modalita' lettura/scrittura, settare il valore a 3, leggere il valore e se e' differente da 3 spengere il Led di Arduino
================================================================= #include <ArduinoBLE.h> BLEService numero("180F"); BLEUnsignedCharCharacteristic casuale("2A19",BLERead | BLENotify); BLEUnsignedCharCharacteristic scrittura("2A30",BLERead | BLEWrite); long previousMillis = 0; byte test =3 ; void setup() { Serial.begin(9600); while (!Serial); pinMode(LED_BUILTIN, OUTPUT); if (!BLE.begin()) { while (1); } BLE.setLocalName("Random"); BLE.setAdvertisedService(numero); numero.addCharacteristic(casuale); numero.addCharacteristic(scrittura); BLE.addService(numero); casuale.writeValue(0); // set initial value for this characteristic scrittura.writeValue(2); BLE.advertise(); } void loop() { int i = 0; BLEDevice central = BLE.central(); if (central) { while (central.connected()) { long currentMillis = millis(); if (currentMillis - previousMillis >= 20) { previousMillis = currentMillis; scrittura.readValue(test); if(test ==3) { Serial.println(test); digitalWrite(LED_BUILTIN, HIGH); } else { Serial.println(test); digitalWrite(LED_BUILTIN, LOW); } } } digitalWrite(LED_BUILTIN, LOW); } }
Per Android ho usato la libreria a questo indirizzo . Ne esistono di piu' complete ma
in questo caso avevo bisogno di semplicita'
=================================================================
Un eesmpio di scambio dati via Bluetooth LE tra una scheda Arduino Nano 33 BLE ed un PC
La Arduino Nano BLE 33 e' una scheda interessante perche' oltre al Bluetooth LE sono disponibili una IMU (LMS9DS1), un microfono digitale (MP34DT05), un sensore di colore e prossimita' (APDS9960), un sensore di pressione atmosferica (LPS22HB), un sensore di umidita' relativa e temperatura (HTS221)
Lo sketch su Arduino apre un servizio su BLE con numero 180F ed una caratteristica 2A19 in cui vengono salvati i dati di un contatore progressivo da 0 a 255 (questo per fare in modo che sul lato PC si sia in grado di vedere se si perdono pacchetti)
Lato Arduino
================================================ #include <ArduinoBLE.h> BLEService numero("180F"); BLEUnsignedCharCharacteristic casuale("2A19",BLERead | BLENotify); long previousMillis = 0; void setup() { Serial.begin(9600); while (!Serial); pinMode(LED_BUILTIN, OUTPUT); if (!BLE.begin()) { while (1); } BLE.setLocalName("Random"); BLE.setAdvertisedService(numero); numero.addCharacteristic(casuale); BLE.addService(numero); casuale.writeValue(0); // set initial value for this characteristic BLE.advertise(); } void loop() { int i = 0; BLEDevice central = BLE.central(); if (central) { digitalWrite(LED_BUILTIN, HIGH); while (central.connected()) { long currentMillis = millis(); if (currentMillis - previousMillis >= 20) { i++; casuale.writeValue(i%255); previousMillis = currentMillis; } } digitalWrite(LED_BUILTIN, LOW); } }
================================================
Per verificare che i dati vengano inviati correttamente si puo' usare gattool
A questo punto con la libreria Bluepy si possono leggere i dati inviati dalla Arduino
================================================ from bluepy import btle from bluepy.btle import UUID, Peripheral addr = "ED:CB:86:2A:68:C1" conn = Peripheral(addr, "public") print ("-Servizi") services = conn.getServices() for service in services: print(service.uuid)
print("-Caratteristica") charac_dic = service.getCharacteristics() for charac in charac_dic: print(charac.uuid) if charac.uuid == "2a19": print ("Trovata") Data_char = charac print(Data_char) Data_handle = Data_char.getHandle() print Data_handle while True: print (ord(charac.read()))
================================================
la trasmissione dati in questo modo e' piuttosto lenta..circa un dato ogni decimo di secondo.
Usando la tecnica di subscribe and notify la Arduino invia i dati al PC senza la necessita' per quest'ultimo di richiederli. Con questa tecnica non si perde nessun pacchetto
================================================
from bluepy import btle from bluepy.btle import UUID, Peripheral import struct def listAll(p): for svc in p.getServices(): print(svc.uuid.getCommonName()) for ch in svc.getCharacteristics(): print(" " + str(ch.valHandle) + ": " + ch.uuid.getCommonName()) class MyDelegate(btle.DefaultDelegate): def __init__(self): btle.DefaultDelegate.__init__(self) def handleNotification(self, cHandle, data): print(ord(data)) addr = "ED:CB:86:2A:68:C1" p = btle.Peripheral(addr,"public") services=p.getServices() for service in services: print(service.uuid) p.setDelegate( MyDelegate() ) listAll(p) svc = p.getServiceByUUID("0000180f-0000-1000-8000-00805f9b34fb") ch = svc.getCharacteristics()[0] p.writeCharacteristic(ch.valHandle+1, b'\x01\x00', withResponse=True) while True: if p.waitForNotifications(1.0): continue print "Waiting..."
Seguendo il precedente post su come poter continuare ad usare Yun nonostante il supporto end-of-life sono riuscito a settate la possiblita' di effettuare la cross compilazione da Debian verso Yun
Per prima cosa si scarica Buildroot e lo si configura (make menuconfig) con target MIPS big endian, ELF MIPS32 con toolchain uCLIb abilitando con Gdb per futuri sviluppi. Fatto cio' si lancia make e si aspetta
A questo punto per rendere piu' semplice la cross compilazione si usa Eclipse CDT
Si crea un nuovo progetto C con Cross GCC e si lasciano in bianco GCC Cross Command che saranno compilati in seguito
Si aprono quindi le proprieta' del progetto Eclipse selezionando Cross GCC in ToolChain Editor
Si setta come Prefix (attenzione al meno finale che deve essere incluso) e Path
tutti i file necessari si trovano nella sottodirectory /output/host/ di Buildroot
Si aggiungono due pathe per le librerie /home/luca/Downloads/buildroot-2019.02.6/output/host/usr/lib /home/luca/Downloads/buildroot-2019.02.6/output/host/mips-buildroot-linux-uclibc/lib
Arrivati fino a qui si puo' compilare il file e copiarlo in scp sulla Yun