martedì 5 marzo 2019

Queue con FreeRTOS su Arduino Uno

Le Queue, code, di FreeRTOs sono metodi per scambiare dati tra due task. In questo esempio una coda monodirezionale (un task invia dati e l'altro li riceve)


-----------------------------------------------------------------
#include <Arduino_FreeRTOS.h>
#include <queue.h>  

QueueHandle_t coda;
int codasize = 10;

void sender( void *pvParameters );
void receiver( void *pvParameters );

void setup() {

  Serial.begin(9600);
  coda = xQueueCreate(codasize,sizeof(int));
  
  if ( coda == NULL )   {
     Serial.println("Errore nella creazione");
  }

  xTaskCreate(sender,(const portCHAR *)"Sender",128,NULL,3,NULL);
  xTaskCreate(receiver,(const portCHAR *)"Receiver",128,NULL,2,NULL);

}

void loop()
{
}



void sender( void *pvParameters __attribute__((unused)) )  // This is a Task.
{
  for (;;)
  {
    for (int t=0;t<5;t++){
      xQueueSend(coda,&t,portMAX_DELAY);
    }
    vTaskDelay( 1000 / portTICK_PERIOD_MS );

  }
}


void receiver( void *pvParameters __attribute__((unused)) )  
{
  int elemento;
  for (;;)
  {
    for (int t=0;t<codasize;t++){
      xQueueReceive(coda,&elemento,portMAX_DELAY);
      Serial.print(elemento);
      Serial.print("|");
    }
    Serial.println();

    vTaskDelay( 1000 / portTICK_PERIOD_MS );
  }
}

Semafori binari in FreeRTOS con Arduino

I semafori binari (o Mutex) sono metodi per stabilire per un task per capire se una risorsa condivisa e' occupata da un altro task (e quindi non utilizzabile) oppure e' disponibile

In questo esempio sono creati due task che ogni 5 secondi si sovrappongono e cercano entrambi di scrivere sulla porta seriale.
----------------------------------------------------------------------------------

#include <Arduino_FreeRTOS.h>
#include <semphr.h>  
SemaphoreHandle_t semaforo;

void blink_even( void *pvParameters );
void blink_odd( void *pvParameters );

void setup() {

  Serial.begin(9600);


  if ( semaforo == NULL )   {
    semaforo = xSemaphoreCreateMutex();  
    if ((semaforo) != NULL)
      xSemaphoreGive((semaforo));  
  }

// crea i due task
  xTaskCreate(blink_even,(const portCHAR *)"BlinkEven",128,NULL,3,NULL);
  xTaskCreate(blink_odd,(const portCHAR *)"BlinkOdd",128,NULL,2,NULL);

}

void loop()
{
}



void blink_even( void *pvParameters __attribute__((unused)) )  
{
  for (;;)
  {// qui viene testato se il semaforo e' settato, se la risorsa e'occupata riprova per 5 tick ..in caso la risorsa
   // rimanga occupata abbandona
    if (xSemaphoreTake(semaforo, ( TickType_t ) 5 ) == pdTRUE )
    {
      Serial.println("Even");
      xSemaphoreGive(semaforo);
    }
    vTaskDelay( 5000 / portTICK_PERIOD_MS );

  }
}


void blink_odd( void *pvParameters __attribute__((unused)) )  
{
  for (;;)
  {
    if (xSemaphoreTake(semaforo, ( TickType_t ) 5 ) == pdTRUE )
    {
      Serial.println("Odd");
      xSemaphoreGive(semaforo);
    }
    vTaskDelay( 1000 / portTICK_PERIOD_MS );
  }
}

Diventare amministratore della macchinetta del caffe'

Per motivi non meglio spiegati (sarebbe interessante scoprire il metodo) la macchinetta del caffe' dell'ufficio e' andata in crisi lasciando aperta una bella shell di amministrazione ...ops menu' di configurazione con cui poter fare qualunque cosa


Per interagire con il menu si possono usare Zucchero - e Zucchero + per andare indietro ed avanti, Caffe' e cioccolato per selezionare (Ok) e Caffe' al gingseng per andare indietro nel menu (i pusalnti sono illuminati in modalita' di amministrazione) 


Si puo' fare di tutto, dal cambiare il prezzo delle varie bevande ad avere le statistiche. Peraltro sembra che la macchinetta possa trasmettere i dati in remoto (non credo invece che possa essere controllata in remoto altrimenti sarebbe gia' stata resettata)



.....e no, non ne ho approfittato..nemmeno un caffe'

lunedì 4 marzo 2019

Mongoose OS ed ESP-Wroom-32

Un paio di indicazioni:
1) Mongoose OS non e' legato a MongoDB e Node.JS...maledetta fantasia nel mettere i nomi
2) in estrema sintesi Mongoose OS e' molto simile al cloud di Particle con la differenza che quest'ultimo e' legato a doppio filo con l'hardware di Particle (Electron, Photon) mentre Mongoose OS puo' essere usato con hardware ESP32 ed STM32



Per inziare ho scaricato il pacchetto generico per Linux

curl -fsSL https://mongoose-os.com/downloads/mos/install.sh | /bin/bash mos

e si lancia il programma in $HOME/.mos/bin/mos

si aprira' il browser di default all'indirizzo http://127.0.0.1:1992/
Le istruzioni dicono di premere CTRL+N per creare una nuova app ma su Chrome per Linux questa combinazione apre una nuova scheda del browser. Si puo' pero' usare la barra in basso allo schermo (vicino all'icona arancione che si trova nell'angolo in basso a destra) per digitare 

mos clone https://github.com/mongoose-os-apps/demo-js app1
a seguire (la compilazione avviente completamente sul cloud...i risultati saranno nella sottodirectory build)

mos build
mos flash 

Per avere la possibilita' di interagire in remoto ed effettuare anche degli OTA update (Over the air) si puo' configurare la connessione con l'access point con 

mos wifi WIFI_NETWORK_NAME WIFI_PASSWORD

Una volta ottenuta la connessione si rete si puo' impostare la connessione al cloud.Ci si collega a  https://dash.mongoose-os.com/ e si crea un nuovo dispositivo (con il profilo gratuito se ne possono creare fino a 3)

si copia il token (basta andare sopra al token) e da http://127.0.0.1:1992/ si digita

mos config-set dash.enable=true dash.token=xxxxxxxxdc08

se tutto e' andato bene il dispositivo comparira' on line nel cloud
Dall'interfaccia Web si puo' impostare il comando remoto tramite Mobile (si tratta di un link)
Si puo' accendere o spengere una porta digitale. Con il modulo ESP-Wroom-32 il pin preimpostato e' il numero 13 (IO13 a destra di GND)

La programmazione successiva puo' avvenire mediante C o Javascript. In generale, leggendo anche il forum, si tratta di un progetto piuttosto immaturo con un supporto ancora scarso con l'hardware (nonostante sia comunque presente la possibilita' di convertire le librerie Arduino nei progetti Mongoose)



venerdì 1 marzo 2019

Impostazione ProtonVPN su Debian 9

Questo e' un promemoria perche' regolarmente mi scordo come si fa ad impostare ProtonVPN su Debian

per prima si installano i pacchetti per openvpn in Network Manager

apt-get install openvpn network-manager-openvpn network-manager-openvpn-gnome


Da Account si copia OpenVPN/IKEv2 Username



e da Download si scaricano i file .ovpn relativi ai server (free nel mio caso) 


Fatto cio' si apre Network Manager/VPN/VPN Settings e si aggiunge il nuovo server importando il file .ovpn ed inserendo come username il precedente OpenVPN/IKEv2 Username e la password


Toolchain per ESP32 su Linux

Post per impostare l'ambiente di sviluppo esp32-idf su Debian 9



si installano i pacchetti

apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing

e successivamente
mkdir esp
cd ~/esp 
git clone -b v3.1.3 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
export IDF_PATH=~/esp/esp-idf 

si scarica il compilatore e lo si decomprime

tar -xzf ~/Downloads/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
si inserisce l'ambiente di sviluppo in Path

export PATH="$HOME/esp/xtensa-esp32-elf/bin:$PATH"
se tutto e' andato bene si puo' andare in $HOME/esp/esp-idf/examples/get-started/hello_world e digitare make per vedere se il progetto si compila (viene generato il bootloader all'indirizzo 0x10000 oltre al programma vero e proprio all'inidirizzo 0x8000). Al termine si puo' digitare

make flash 

per copiarlo sulla scheda (questi i messaggi)

-----------------------------------------
Flashing binaries to serial port /dev/ttyUSB0 (app at offset 0x10000 )...
esptool.py v2.6
Serial port /dev/ttyUSB0
Connecting....
Chip is ESP32D0WDQ6 (revision 0)
Features: WiFi, BT, Dual Core, Coding Scheme None
MAC: 24:0a:c4:05:df:5c
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0220
Compressed 21184 bytes to 12506...
Wrote 21184 bytes (12506 compressed) at 0x00001000 in 1.1 seconds (effective 153.7 kbit/s)...
Hash of data verified.
Compressed 144080 bytes to 68379...
Wrote 144080 bytes (68379 compressed) at 0x00010000 in 6.0 seconds (effective 190.8 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 103...
Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.0 seconds (effective 1843.8 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
---------------------------------------------------

Collegandosi con minicom alla /dev/ttyUSB0 si ottengono le seguenti stringhe
---------------------------------------------------
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)                          
configsip: 0, SPIWP:0xee                                                        
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00         
mode:DIO, clock div:2                                                           
load:0x3fff0018,len:4                                                           
load:0x3fff001c,len:5804                                                        
load:0x40078000,len:9188                                                        
load:0x40080000,len:6084                                                        
entry 0x4008032c                                                                
I (29) boot: ESP-IDF v3.1.3 2nd stage bootloader                                
I (29) boot: compile time 11:25:47                                              
I (29) boot: Enabling RNG early entropy source...                               
I (34) boot: SPI Speed      : 40MHz                                             
I (38) boot: SPI Mode       : DIO                                               
I (42) boot: SPI Flash Size : 4MB                                               
I (46) boot: Partition Table:                                                   
I (49) boot: ## Label            Usage          Type ST Offset   Length         
I (57) boot:  0 nvs              WiFi data        01 02 00009000 00006000       
I (64) boot:  1 phy_init         RF data          01 01 0000f000 00001000       
I (72) boot:  2 factory          factory app      00 00 00010000 00100000       
I (79) boot: End of partition table                                             
I (83) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x07180 ( 2p
I (102) esp_image: segment 1: paddr=0x000171a8 vaddr=0x3ffb0000 size=0x022a0 ( d
I (106) esp_image: segment 2: paddr=0x00019450 vaddr=0x40080000 size=0x00400 ( d
I (110) esp_image: segment 3: paddr=0x00019858 vaddr=0x40080400 size=0x067b8 ( d
I (130) esp_image: segment 4: paddr=0x00020018 vaddr=0x400d0018 size=0x11150 ( p
I (155) esp_image: segment 5: paddr=0x00031170 vaddr=0x40086bb8 size=0x02130 ( d
I (164) boot: Loaded app from partition at offset 0x10000                       
I (164) boot: Disabling RNG early entropy source...                             
I (166) cpu_start: Pro cpu up.                                                  
I (170) cpu_start: Starting app cpu, entry point is 0x40080e74                  
I (162) cpu_start: App cpu up.                                                  
I (181) heap_init: Initializing. RAM available for dynamic allocation:          
I (187) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM                       
I (193) heap_init: At 3FFB32F8 len 0002CD08 (179 KiB): DRAM                     
I (200) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM                    
I (206) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM                   
I (213) heap_init: At 40088CE8 len 00017318 (92 KiB): IRAM                      
I (219) cpu_start: Pro cpu start user code                                      
I (237) cpu_start: Starting scheduler on PRO CPU.                               
I (0) cpu_start: Starting scheduler on APP CPU.                                 
Hello world!                                                                    
This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 0, 4MB exterh
Restarting in 10 seconds...                                                     
Restarting in 9 seconds...                                                      
Restarting in 8 seconds...                                                      
Restarting in 7 seconds...                                                      
Restarting in 6 seconds...                                                      
Restarting in 5 seconds...                                                      
Restarting in 4 seconds...                                                      
Restarting in 3 seconds...                                                      
Restarting in 2 seconds...                                                      
Restarting in 1 seconds...                                                      
Restarting in 0 seconds...                                                      
Restarting now.

-------------------------------------------------------
Questo comportamento e' coerente con il programma hello_world.c

---------------------------------------------
/* Hello World Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"


void app_main()
{
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("silicon revision %d, ", chip_info.revision);

    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    for (int i = 10; i >= 0; i--) {
        printf("Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    printf("Restarting now.\n");
    fflush(stdout);
    esp_restart();
}
------------------------------------------------------

In conclusione l'ambiente di sviluppo e' funzionante

Calcolo durata batteria per mini progetti

Fino ad oggi calcolavo la durata teorica di funzionamento di un utilizzatore (tipicamente una Arduino) connesso ad una batteria LiPo dividendo i mAh della batteria per il consumo in ampere dell'utilizzatore



Per esempio: con una batteria da 2500 mAh ed una Arduino Uno in configurazione base con consumo da 45 mA stimavo il tempo di funzionamento in 2500 mAh/45 mA cioe' circa 55 ora

In realta' il calcolo e' sbagliato perche' si deve tenere conto della potenza in Watt (o meglio si deve tenere in conto della potenza nel caso in cui il voltaggio della batteria e dell'utilizzatore sono identici ....ma questo e' un caso particolare)

Prendendo l'esempio precedente una batteria LiPo da 2500 mAh con un 3.7 ha un potenza di 9.25 Wh, La Arduino Uno ha un consumo di circa 45mA a 5 V pèari a 0.225 W. Dividendo 9.25 Wh per 0.225 h si ottiene che il tempo di funzionamento di circa 41 ore (valore sensibilmente differente dal calcolo, errato, precedente)

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...