lunedì 30 dicembre 2024

Ollama e Jetson Nano 4G

Ancora nel tentativo di utilizzare in modo serio la Jetson Nano ho provato ad usarla per Ollama seguendo le istruzioni da https://dev.to/ajeetraina/running-ollama-2-on-nvidia-jetson-nano-with-gpu-using-docker-hfi (e' stato usato il docker perche' usando lo script di installazione dal sito di Ollama fallisce per la necessita' di capabilitie maggiore di quella disponibile da Jetson Nano)

Per creare il docker si seguono i comandi

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
    | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
    | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
    | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update


sudo apt-get install -y nvidia-container-toolkit


sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker


sudo docker run -d --gpus=all --runtime nvidia -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama

sudo docker exec -it ollama ollama run llama2


Alcune persone su Github si lamentano che il docker non sfrutti la GPU della Jetson ma installando il comando jtop (tramite  sudo pip3 install -U jetson-stats) si vede che il carico sulla GPU non e' a zero

schermata di jtop

Per vedere se ollama e' in fuzione basta bussare alla porta 11434



La mia Jetson ha una ram di 4Gb ma solo pochi modelli sono in grado di girare (a meno di non quantizzarli)

Funzionano i seguenti modelli

tinyllama

llama3.2:1b

starcoder:1b 

Non funzionano invece  

orca-mini:3b (ncessita 5.1 GiB di ram )

mistral-small (necessita 14.4 Gib)

llama3.2


Per interagire si puo' installare web ui (che e' in generale decisamente piu' lenta della linea di comando) tramite il docker


docker run -d -p 3000:8080 --runtime=nvidia --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui2 --restart always ghcr.io/open-webui/open-webui:cuda


docker run -d -p 3000:8080 --gpus all --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:cuda



L'unico aspetto veramente positivo di Jetson nano e' il consumo massimo di 5W



comunque a questo semplice prompt l'AI TinyLLama ha fatto una serie veramente sanguionosa di errori

>>> raccontami la storia di Albert Einstein

Einstein, uno dei più grandi pensatori e fisici del XX secolo, nacque nel 1879 a Ulm, in Germania. La sua infanzia fu caratterizzata da una forte intesa con gli  elementi naturali e una grande affinità per la matematica.Nel 1890 Einstein iniziò le sue scuole medie a Kiel e Karlsruhe, dove cominciò a studiare fisica e matematica. Nel 1896 si unì al Liceo Max Planck di Göttingene, dove incontrò il suo futuro compagno di insegnamento, Max Planck.Einstein studiò filosofia, letteratura e lingue, ma la sua vera passione era la fisica. Durante i suoi primi anni universitari, si avvicinò alla teoria della relatività Speciala di Albert Michelson e George Gamow, che cercavano di spiegare l'effetto fotoelettrico.Nel 1905 Einstein pubblicò i suoi esperimenti sull'effetto elettronico, che dimostrarono la connessione tra le onde e le particelle. Questa scoperta lo aprì alla teoria della relatività generale di Albert Einstein, sviluppata dopo il 1905. Nel 1914 Einstein si unì al corpo terrestre militare tedesco durante la Prima Guerra Mondiale e fu catturato dai soldati austriaci. Durante l'arresto Einstein scrisse la sua famosa lettera a Max Planck, in cui chiese di essere reso responsabile per il tempo di vita che aveva trascorso nella prigione. Nel 1919 Einstein ricevette la medaglia Nobel per la fisica per la sua teoria della relatività generale. Tuttavia, ricevette anche una serie di minacce e messaggi oscure, tra cui un'ultima minaccia che lo costringe a lasciare l'Austria nel 1933.Durante il regime nazista, Einstein si ritirò in Svizzera, dove continuò a studiare fisica. Nel 1932 ricevette la medaglia Copley per la sua carriera accademica. Tuttavia, si unì all'Ordine di Malta nel 1933 e fu invitato a lasciare gli Stati Uniti. Nel 1935 Einstein pubblicò il suo libro "La relatività generale", che divenne un successo internazionale. Tuttavia, ricevette sempre più minacce e messaggi oscari, e nel 1938 scrisse la sua famosa formula dell'Einstein-Rosen bridge. Durante l'Anno di Natale 1939 Einstein fu attaccato con una bomba atomica a Praga, in Cecoslovacchia. La sua salute si deteriorò ulteriormente negli anni successivi e morì il 18 April 1955 a Princeton, nel New Jersey. Einstein lasciò un'impronta indelebile sulla scienza e nella cultura, e la sua teoria della relatività generale rimane una delle fondamenta fondazionali dell'attuale fisica. La sua storia è un esempio di come la curiosità, l'iniziativa e la determinazione possano portare a grandi risultati scientifici.





sabato 28 dicembre 2024

Feature Matching OpenCv

Il problema e' il seguente: trovare le differenze tra le due foto. Le due immagini sono state riprese a distanza di oltre un anno ed il punto di ripresa non e' esattamente il solito per cui c'e' un effetto di traslazione e rotazione seppure non immediatamente

Prima

Dopo

Con lo script sottostante sono state estratte le feature tramite AKAZE e successivamente sono state matchate e filtrate in base alla distanza tramite FLANN

E' stata calcolata la distanza in pixel tra il punto nella prima immagine ed il suo omologo nella seconda sottraendo un valore costante derivante (1000) e colorando il punto secondo la scala colore da verde a rosso a secondo dell'intensita' di movimento

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
import math

originale = cv.imread(filename = 'prima.png')
originale2 = cv.imread(filename = 'prima.png')

image1 = cv.imread(filename = 'prima.png',flags = cv.IMREAD_GRAYSCALE)
image2 = cv.imread(filename = 'dopo.png',flags = cv.IMREAD_GRAYSCALE)
AKAZE = cv.AKAZE_create()

# Find the keypoints and compute the descriptors for input and training-set image
keypoints1, descriptors1 = AKAZE.detectAndCompute(image1, None)
keypoints2, descriptors2 = AKAZE.detectAndCompute(image2, None)

# FLANN parameters
FLANN_INDEX_KDTREE = 1

index_params = dict(algorithm = FLANN_INDEX_KDTREE,trees = 5)
search_params = dict(checks = 50)

# Convert to float32
descriptors1 = np.float32(descriptors1)
descriptors2 = np.float32(descriptors2)

# Create FLANN object
FLANN = cv.FlannBasedMatcher(indexParams = index_params,searchParams = search_params)

# Matching descriptor vectors using FLANN Matcher
matches = FLANN.knnMatch(queryDescriptors = descriptors1,
trainDescriptors = descriptors2,
k = 2)

ratio_thresh = 0.7
good_matches = []
for m, n in matches:
if m.distance < ratio_thresh * n.distance:
distanza = math.sqrt(pow((keypoints1[m.queryIdx].pt[0] - keypoints2[n.trainIdx].pt[0]), 2) + pow((keypoints1[m.queryIdx].pt[1] - keypoints2[n.trainIdx].pt[1]), 2))
distanza = distanza - 1000
colore = (0, 0, 0)
if (distanza <500.0):
colore = (73, 245, 109)
if (distanza >= 500) and (distanza <1000):
colore = (90, 248, 98)
if (distanza >= 1000) and (distanza <1500):
colore = (154, 244, 87)
if (distanza >= 1500) and (distanza <2000):
colore = (228, 178, 45)
if (distanza >= 2000) and (distanza <2500):
colore = (248, 38, 49)
if distanza >= 2500.0 :
colore = (255, 0, 27)
#print(m.distance)
cv.circle(originale, (int(keypoints2[m.trainIdx].pt[0]), int(keypoints2[m.trainIdx].pt[1])), 15, colore, -1)
good_matches.append(m)


plt.imshow(originale)
plt.show()














mercoledì 18 dicembre 2024

Debugger integrato ESP32S3

Aggiornamento

In realta' il Jtag USB funziona anche sui moduli cinesi

Il problema risiede  nell'ID USB della porta Jtag. Nel modulo Espressif originale si trova in 303a:1001 mentre nel modulo cinese si trova in 303a:4001

Si deve quindi modificare la configurazione di OpenOCD nel file

/.espressif/tools/openocd-esp32/v0.12.0-esp32-20240821/openocd-esp32/share/openocd/scripts/interface/esp_usb_jtag.cfg 

espusbjtag vid_pid 0x303a 0x4001
espusbjtag caps_descriptor 0x2000


modificando Pid da 1001 a 4001 ed aggiungendo la regola in udev 

ATTRS{idVendor}=="303a", ATTRS{idProduct}=="4001", MODE="664", GROUP="plugdev", TAG+="uaccess

--------------------------------------------------------------------------------------------------------

La Esp32S3 espone sui pin 19 e 20 una porta USB che puo' essere usata per fare debug....ma attenzione...questo e' valido per il DevKit ufficiale di Espressif ma non funziona con i moduli cinesi (ci sono impazzito dietro a questa cosa)

 

Si deve creare un cavo usb tagliandone uno, giuntando dei cavi Dupount femmina e connettendo

D+ (verde) a GPIO19

D- (bianco) a GPIO20

GND (nero) a GND (forse non necessario)




a questo punto connettendo la scheda con lsusb si legge Espressif USB Jtag Serial (che si e' andato su /dev/ttyACM0) come debugger e CP210x UART Bridge come /dev/ttyUSB0 per la normale connessione con Esp32

a questo punto si ha il seguente errore nell'avviare il server OpenOCD

libusb_open() failed with LIBUSB_ERROR_ACCESS

prima di tutto si deve inserire l'utente nel gruppo plugdev

sudo usermod -a -G plugdev luca

poi si crea un file 99-jtag.rules con contenuto 

ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="664", GROUP="plugdev", TAG+="uaccess"

e lo si copia in /etc/udev/rules.d. (i valori sono ripresi da comando lsusb). Si aggiorna plugdev

sudo udevadm control --reload-rules & sudo udevadm trigger

si avvia il server OpenOcd

openocd -f board/esp32s3-builtin.cfg

e poi da dentro Visual Code plugin ESP-IDF si clicca su Flash (se il progetto e' configurato bene inizia anche il debug) Select Flash Mode JTAG port /dev/ttyUSB0

ed ecco alla fine avviata la sessione di debug usando l'esempio Fibonacci




JRP7008

Schermo a risoluzione 1024x600 con connessione HDMI.

Lo ho comprato a 35 euro


per utilizzarlo con Raspberry si modifica il file confix.txt nella SdCard

max_usb_current=1
hdmi_force_hotplug=1
config_hdmi_boost=10
hdmi_group=2
hdmi_mode=87
hdmi_cvt 1024 600 60 6 0 0 0

 

Lo schermo si puo' usarea come display secondario su Debian senza nessuna ulteriore configurazione


 

 

Arducam IMX519 16 Mpx

Ho provato la Arducam 16 Mpx basata sul sensore Sony IMX519

 


 Per prima cosa c'e' da evindenziare che il supporto non e' nativo su Raspberry a differenza delle PiCam. Le istruzioni per montare il driver si trovano a questo link 

 https://docs.arducam.com/Raspberry-Pi-Camera/Native-camera/16MP-IMX519/


La camera si utilizza con libcamera e permette di salvare in DNG  e raw

domenica 15 dicembre 2024

Topotag

Aggiornamento

da esplicita richiesta su GitHub gli sviluppatori mi hanno indicato che la licenza d'uso e' solo per ricerca ed e' esplicitamente vietato l'uso commerciale

-------------------------------------------------------------------------------------------

Nella grande famiglia dei fiducial markers ho trovato i Topotag che promettono di surclassare Apriltag e Arucotag

Il codice della libreria si trova su Github https://github.com/herohuyongtao/topotag  ma si deve evidenziare che viene distribuita solo in formato binario per Windows .dll (niente Linux) senza specificare il tipo di licenza

I due file binari (generator e detector) funzionano a linea di comando passando i parametri tramite il file yaml

 


 


 

 


 


 

 

 

giovedì 12 dicembre 2024

Deep Tag

Ho provato un riconoscimento neurale di tag (di varia natura ma nel mio caso Aruco ed Apriltag) mediante il codice presente  https://github.com/herohuyongtao/deeptag-pytorch

L'articolo di riferimento si trova qui

La configurazione e' fatta tramite un file json (nel mio caso ho provato sia il video via webcam sia una foto  con l'esempio sottostante)

Un aspetto da non trascurare e' che il software richiede oltre al punto principale cx,cy alla lunghezza focale fx,fy ed i coefficienti di distorsione radiale k1-k6 anche i coefficienti di distorsione tangenziale p1 2 p2 che con gli esempi di opencv non vengono calcolati (ho impostato a zero in quanto non li avevo disponibili)

Anche senza l'uso di GPU il calcolo e' abbastanza spedito (non proprio realtime ma si avvicina)



{
"is_video":0,
"filepath":"q/novembre.jpg",
"family": "aruco",
"hamming_dist": 8,
"codebook": "",
"cameraMatrix": [2694.308, 0, 1793.8734, 0, 2704.6156, 1058.7691, 0, 0, 1],
"distCoeffs": [-0.41168919, 0.26635946, -0.0017025, 0.00744752, -0.16179997, 0, 0, 0],
"marker_size": 0.25
}
 

martedì 10 dicembre 2024

CH57x

Volevo costruirmi un controller fisico per VLC con almeno un comando rotativo (volevo utilizzare M5Dial) da usare mentre cerco di suonare per rallentare o ripetere la traccia quando ho visto su Aliexpress era gia' pronto e montato ad un prezzo ragionevole (meno di 15 euro)...cablato e non Bluetooth ma va bene lo stesso 



 

Il problema e' che quando e' arrivato era completamente senza istruzioni e non si riusciva a capirne il funzionamento

Frugando ho trovato il progetto  

https://github.com/YetiOSS/the-ch57x-keyboard-tool/ 

che permette di configurare tramite un file yaml il comportamento 

======================================

orientation: normal
rows: 1
columns: 3
knobs: 1

layers:
  - buttons:
      - ["3", "5", "6"]
    knobs:
      - ccw: 'wheeldown'
        press: "space"
        cw: "wheelup"

====================================== 

./ch57x-keyboard-tool upload < config.yaml

una volta programmato la configurazione e' permanente e non e' necessario ripetere l'operazione

Premendo il knob ho il play/stop, girando il knob va avanti ed indietro, su 5, 6 controllo la velocita' di riproduzione 

Non sono riuscito a configurare le combinazioni di tasti anche se dal manuale sembra possibile

 

 

giovedì 5 dicembre 2024

Pi Cam HQ e telescopio

Ho provato ad accoppiare la Pi Cam HQ module 12 MPx (vecchiotta ma e' sempre un sensore Sony) con un spotting scope della Celestron MK70 MiniMak (fortunatamente comprato di seconda mano). E' stato impiegato un adattatore da CS (lato PiCam) ad oculare 1.25 inch (standard telescopi) stampato 3D la filettatura non era perfetta ma il fatto di essere fatto di plastica permette un buon accoppiamento forzando un po' 





ho usato una flat lunga 







La zona inquadrata era l'insegna del negozio di elettronica ...la zona e' indicata dalla freccia blu


questo e' il risultato tramite il telescopio


direi un ottimo risultato 




venerdì 29 novembre 2024

ESP32 logger low power

A seguito del precedente post in questo caso il logger e' stato fatto con una ESP32S3 






Al contrario di Arduino dove i dati erano salvati su SD card qui vengono salvati sulla memoria interna tramite Littefs. Al primo avvio viene cancellato il file dati poi vengono salvati i dati in append dell'ADC, inoltre 

 

E' stato usato il deep sleep tramite RTC. In questo modo la ESP32 effettua un riavvio completo ogni tot secondi..la variabile conta serve come contatore progressivo dei riavvii in modo che al primo ciclo vengano eseguiti specifici. la variabile conta e' dichiarata come RTC_DATA_ATTR in modo da non essere volatile ed essere preservata nella fase di deep sleep

Anche se non precisssimo quando in deep l'RTC continua a funzionare...si setta quindi la data ed ora al primo riavvio e poi si legge il tempo aggiornato ai successivi riavvii. 

 Usando lo sketch della sola lettura analogica di un pin ESP32 consuma circa 19 mA



in deep sleep il consumo crolla al livello delle decine di  microA tanto che la mia schedina non riesce a rilevarlo

 


per usare LittleFs si deve aggiungere il componente in idf_component.yml

dependencies:
joltwallet/littlefs: "==1.14.8"
## Required IDF v

modificare sdkconfig per indicare il file dove sono settate le impostazioni della partizione (in questo caso il file csv)

# Partition Table
#
# CONFIG_PARTITION_TABLE_SINGLE_APP is not set
# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_demo_esp_littlefs.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions_demo_esp_littlefs.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_MD5=y
# end of Partition Table


e creare il corrispondente file 

nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 1M,
littlefs,  data, spiffs,      ,  0xF0000,

questo il codice finale

include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "driver/rtc_io.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "deep_sleep_example.h"

#include <time.h>
#include <sys/time.h>

#include "driver/gpio.h"
#define PIN GPIO_NUM_35

#include "esp_system.h"
#include "spi_flash_mmap.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_littlefs.h"
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>


#include "driver/adc.h"
#include "esp_adc_cal.h"



/*
#if SOC_RTC_FAST_MEM_SUPPORTED
static RTC_DATA_ATTR struct timeval sleep_enter_time;
#else
static struct timeval sleep_enter_time;
#endif
*/
RTC_DATA_ATTR int conta =0;

struct tm tm;

static void deep_sleep_task(void *args)
{
esp_deep_sleep_start();
}

static void deep_sleep_register_rtc_timer_wakeup(void)
{
const int wakeup_time_sec = 15;
conta = conta + 1;
gpio_set_direction(PIN, GPIO_MODE_OUTPUT);
gpio_set_level(PIN, 0);
vTaskDelay(100);
gpio_set_level(PIN, 1);

struct timeval tv;
char buffer[30];
time_t curtime;
gettimeofday(&tv, NULL);
curtime=tv.tv_sec;
strftime(buffer,30,"%m-%d-%Y %T.",localtime(&curtime));
printf("Orario %s%ld\n",buffer,tv.tv_usec);

esp_adc_cal_characteristics_t adc1_chars;
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_11);
int adc_value = adc1_get_raw(ADC1_CHANNEL_4);
static const char *TAG = "demo_esp_littlefs";

ESP_LOGI(TAG, "Initializing LittelFS");

esp_vfs_littlefs_conf_t conf = {
.base_path = "/littlefs",
.partition_label = "littlefs",
.format_if_mount_failed = true,
.dont_mount = false,
};

// Use settings defined above to initialize and mount LittleFS filesystem.
// Note: esp_vfs_littlefs_register is an all-in-one convenience function.
esp_err_t ret = esp_vfs_littlefs_register(&conf);

if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
ESP_LOGE(TAG, "Failed to mount or format filesystem");
}
else if (ret == ESP_ERR_NOT_FOUND)
{
ESP_LOGE(TAG, "Failed to find LittleFS partition");
}
else
{
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
}
return;
}

size_t total = 0, used = 0;
ret = esp_littlefs_info(conf.partition_label, &total, &used);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Failed to get LittleFS partition information (%s)", esp_err_to_name(ret));
}
else
{
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}

// Use POSIX and C standard library functions to work with files.
// First create a file.
ESP_LOGI(TAG, "Opening file");
FILE *f = fopen("/littlefs/dati.txt", "a");
if (f == NULL)
{
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f,"%s%ld, %i\n",buffer,tv.tv_usec,adc_value);
fclose(f);
ESP_LOGI(TAG, "File written");
ESP_LOGI(TAG, "Reading file");
f = fopen("/littlefs/dati.txt", "r");
if (f == NULL)

{
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}

int c;
while ((c = getc(f)) != EOF)
putchar(c);

//char line[64];
//fgets(line, sizeof(line), f);
fclose(f);

// All done, unmount partition and disable LittleFS
esp_vfs_littlefs_unregister(conf.partition_label);
ESP_LOGI(TAG, "LittleFS unmounted");



printf("conteggio %d\n",conta);
//printf("Minuti: %llu\n",tv.tv_sec);
printf("Stato: %d\n",adc_value);
printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
}

void app_main(void)
{

gpio_set_direction(PIN, GPIO_MODE_OUTPUT);
gpio_set_level(PIN, 1);

tm.tm_year = 2024 - 1900;
tm.tm_mon = 11;
tm.tm_mday = 27;
tm.tm_hour = 13;
tm.tm_min = 23;
tm.tm_sec =10;

if (conta < 2) {
time_t t = mktime(&tm);
struct timeval now = { .tv_sec = t };
settimeofday(&now, NULL);

static const char *TAG = "esp_littlefs";

esp_vfs_littlefs_conf_t conf = {
.base_path = "/littlefs",
.partition_label = "littlefs",
.format_if_mount_failed = true,
.dont_mount = false,
};

esp_err_t ret = esp_vfs_littlefs_register(&conf);

if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find LittleFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
}
return;
}

if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find LittleFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
}
return;
}

struct stat st;

if (stat("/littlefs/dati.txt", &st) == 0) {
// Delete it if it exists
unlink("/littlefs/dati.txt");
}
else{
ESP_LOGE(TAG, "File non cancellato");

}
esp_vfs_littlefs_unregister(conf.partition_label);
ESP_LOGI(TAG, "LittleFS unmounted");
}

deep_sleep_register_rtc_timer_wakeup();
xTaskCreate(deep_sleep_task, "deep_sleep_task", 4096, NULL, 6, NULL);
}


 

giovedì 28 novembre 2024

Arduino logger low power

Aggiornamento:

ho interrotto l'esperimento prima della fine effettiva della batteria

L'Arduino e' rimasta attiva dalle 8:37 del 1/11/2024 alle 8:50 del 15/12/2024 partendo da circa 4.3 V per terminare a 3.91 V ed ha effettuato 31424 misure dal sensore di torbidita'

Al di sotto il grafico di scarica



================================================

 

Alla fine ci sono riuscito

La arduino MKR zero e' ormai da un mese che e' rimasta accesa sul tavolo...o meglio si attiva ogni minuto, legge il pin 0, legge lo stato della carica della batteria, scrive sulla Sd card e si addormenta in deep sleep

la batteria da 6600 mAh e' costituita da 18650

 


 

 

#include "ArduinoLowPower.h"
#include <SD.h>
#include <RTCZero.h>

RTCZero rtc;

/* Change these values to set the current initial time */
const byte seconds = 00;
const byte minutes = 05;
const byte hours = 14;

/* Change these values to set the current initial date */
const byte day = 01;
const byte month = 11;
const byte year = 24;


const int chipSelect = SDCARD_SS_PIN;
int i;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  delay(1000);
  SD.begin(chipSelect);

  rtc.begin(); // initialize RTC
  rtc.setHours(hours);
  rtc.setMinutes(minutes);
  rtc.setSeconds(seconds);
  rtc.setDay(day);
  rtc.setMonth(month);
  rtc.setYear(year);

}

void loop() {
  if (i == 60) {
              digitalWrite(LED_BUILTIN, HIGH);
              delay(500);
              digitalWrite(LED_BUILTIN, LOW);
              delay(500);

              int batteria = analogRead(ADC_BATTERY);
              float voltage = batteria * (4.3 / 1023.0);
              if (voltage < 3.9)
                {
                 for (i=1;i<10;i++)
                 {
                  digitalWrite(LED_BUILTIN, HIGH);
                  delay(50);
                  digitalWrite(LED_BUILTIN, LOW);
                  delay(50);
                }
              }
            
              File dataFile = SD.open("data.txt", FILE_WRITE);

              int sensor = analogRead(0);
              String anno = String(rtc.getYear());
              String mese = String(rtc.getMonth());
              String giorno = String(rtc.getDay());
              String ora = String(rtc.getHours());
              String minuto = String(rtc.getMinutes());
              String secondo = String(rtc.getSeconds());

              if (mese.length() == 1) {mese = "0"+ mese;}
              if (giorno.length() == 1) {giorno = "0"+ giorno;}
              if (ora.length() == 1) {ora = "0"+ ora;}
              if (minuto.length() == 1) {minuto = "0"+ minuto;}
              if (secondo.length() == 1) {secondo = "0"+ secondo;}
             
              if (dataFile) {
                dataFile.println(anno+"/"+mese+"/"+giorno+"-"+ora+":"+minuto+":"+secondo+";"+String(sensor)+";"+String(voltage));
                dataFile.close();
                }
              i = 0;
              }
  i++;
  LowPower.sleep(1000);
}

Pandas su serie tempo

Problema: hai un csv che riporta una serie tempo datetime/valore di un sensore Effettuare calcoli, ordina le righe, ricampiona il passo temp...