Mi sono trovato a dover installare Debian su un Ultrabook Lenovo X1 Carbon e dover seguire una procedura mai provata.
Di solito installo i driver della scheda WiFi al secondo riavvio, anche perche' i driver sono spesso proprietari, usando la Ethernet per scaricare la distribuzione (Debian testing e' scaricabile solo come netinst)
X1 Carbon non ha una Ethernet integrata ed il dongle USB della Lenovo monta un Realtek 8153 il cui driver non e' compreso nel Cd di installazione
Come fare allora. Arrivato a questa schermata ho trovato il firmware della scheda di rete Wireless del Carbon (iwlwifi-7260-17.ucode), ho scaricato il file .dpgk su un altro computer, lo ho scompattato con ar e salvato il file .ucode (nel pacchetto ve ne sono molti altri) su una chiavetta USB
A questo punto ho rimosso il supporto USB con la iso Debian e messo quello con il driver. L'installer ha preso al volo il cambio di chiavetta e montato il driver attivando il WiFi. E' pero' necessario continuare l'installazione con il supporto di installazione e qui le cose si fanno un po' piu/ complicate.,...reinserendo la chiavetta di installazione questa non viene montata in automatico. Si deve entrare in shell (CTRL+ALT+F4) e montare a mano la chiavetta su /cdrom.
A questo punto si ritorna sulla finestra dell'installer (CTRL+ALT+F7) per terminare la configurazione
martedì 15 gennaio 2019
SSR Relay a stato solido per Arduino
Per un progetto in cui mi serve un relay ho voluto provare a sostituire un rele' meccanico con uno a stato solido (in particolare un modulo da due SSR della Keyestudio)
Lo ho connesso come d'uso per i relay ad una Arduino Uno e non avevo interruzione di corrente al dispositivo
Dopo un po' di pensatoio ho provato ad isolare il problema.
A componente singolo attaccato ad Arduino l'SSR presenta due stati: uno a resistenza infinita (ops....molto molto alta sopra la scala del multimetro) ed uno stato di circa 6 KOhm...in pratica c'e' uno stato disconnesso ed uno con una resistenza non trascurabile....non c'e' praticamente circuitazione tra i due connettori quando il rele' e' chiuso
Se attacco un carico sui terminali la cosa diventa ancora piu' strana....in pratica il rele' non interrompe mai la connessione tra gli elettrodi... alla fine sono capitato su questo documento in cui viene spiegato il motivo per cui un rele' non fa il suo lavoro
Torno ai rele' meccanici....
Lo ho connesso come d'uso per i relay ad una Arduino Uno e non avevo interruzione di corrente al dispositivo
Dopo un po' di pensatoio ho provato ad isolare il problema.
A componente singolo attaccato ad Arduino l'SSR presenta due stati: uno a resistenza infinita (ops....molto molto alta sopra la scala del multimetro) ed uno stato di circa 6 KOhm...in pratica c'e' uno stato disconnesso ed uno con una resistenza non trascurabile....non c'e' praticamente circuitazione tra i due connettori quando il rele' e' chiuso
Se attacco un carico sui terminali la cosa diventa ancora piu' strana....in pratica il rele' non interrompe mai la connessione tra gli elettrodi... alla fine sono capitato su questo documento in cui viene spiegato il motivo per cui un rele' non fa il suo lavoro
Torno ai rele' meccanici....
lunedì 14 gennaio 2019
Arduino Sleep Mode e risveglio con Interrupt da DS3231
Arduino ha diverse modalita' di funzionamento, oltre a quella standard, per ridurre al minimo il consumo di una eventuale batteria. La modalita' sleep mode interna al processore prevede un watchdog che puo' essere settato al massimo ad 8 secondi; per ottenere dei tempi di sleep mode piu' lunghi di deve fornire al microprocessore un segnale dall'esterno che viene gestito come interrupt
Per fornire tale segnale esterno uno dei metodi piu' comodi e' quello di usare un RTC che preveda il canale SQW come il DS3231 (che peraltro risulta essere molto piu' preciso del DS1307)
Il DS3231 funzione su I2C per cui le connessioni sono VCC=3.3 V (attenzione), GND, SDA su A4 Arduino e SCL su A5 Arduino. In piu' si deve collegare SQW sul Pin dell'Arduino per avere segnale di risveglio
Sul DS3231 ci sono due allarmi ma ne sara' usato uno che dopo ogni utilizzo sara' spostato di 60 minuti nel futuro e subito dopo la scheda sara' messa in sleep mode in attesa di essere risvegliata
Il codice del loop riparte dall'ultima istruzione eseguita prima di essere andata in sleep
-------------------------------------------------------------------------------------------------
#include <Wire.h>
#include <RTClibExtended.h>
#include <LowPower.h>
#define wakePin 2
RTC_DS3231 rtc;
//-------------------------------------------------
void wakeUp() // here the interrupt is handled after wakeup
{
}
//------------------------------------------------------------
void setup() {
Serial.begin(9600);
delay(3000);
//imposta il PIN D2 per il wqakeup
pinMode(wakePin, INPUT);;
Wire.begin();
rtc.begin();
rtc.adjust(DateTime(__DATE__, __TIME__)); //imposta l'orologio in fase di compilazione col computer
//elimina allarmi eventualmente presenti
rtc.armAlarm(1, false);
rtc.clearAlarm(1);
rtc.alarmInterrupt(1, false);
rtc.armAlarm(2, false);
rtc.clearAlarm(2);
rtc.alarmInterrupt(2, false);
rtc.writeSqwPinMode(DS3231_OFF);
delay(1000);
Serial.println("Inizio");
}
//------------------------------------------------------------
void loop() {
DateTime now = rtc.now();
Serial.print(now.hour(),DEC);
Serial.print(":");
Serial.print(now.minute(),DEC);
Serial.print(":");
Serial.print(now.second(),DEC);
Serial.println();
//calcola la prossima ora di risveglio ovvero dopo un'ora
DateTime nextAlarm = now + TimeSpan(0, 1, 0, 0);
// l'ordine del timespan e' giorni,ore,minuti,secondi
rtc.setAlarm(ALM1_MATCH_HOURS, nextAlarm.minute(), nextAlarm.hour(), nextAlarm.second()); //imposta l'allarme
rtc.alarmInterrupt(1, true);
delay(3000); // wait for console
attachInterrupt(0, wakeUp, LOW);
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //entra in sleep su questa istruzione
detachInterrupt(0); //execution resumes from here after wake-up
//cancella la precedente impostazione dell'allarme 1
rtc.armAlarm(1, false);
rtc.clearAlarm(1);
rtc.alarmInterrupt(1, false);
delay(3000);
}
Per fornire tale segnale esterno uno dei metodi piu' comodi e' quello di usare un RTC che preveda il canale SQW come il DS3231 (che peraltro risulta essere molto piu' preciso del DS1307)
Il DS3231 funzione su I2C per cui le connessioni sono VCC=3.3 V (attenzione), GND, SDA su A4 Arduino e SCL su A5 Arduino. In piu' si deve collegare SQW sul Pin dell'Arduino per avere segnale di risveglio
Sul DS3231 ci sono due allarmi ma ne sara' usato uno che dopo ogni utilizzo sara' spostato di 60 minuti nel futuro e subito dopo la scheda sara' messa in sleep mode in attesa di essere risvegliata
Il codice del loop riparte dall'ultima istruzione eseguita prima di essere andata in sleep
-------------------------------------------------------------------------------------------------
#include <Wire.h>
#include <RTClibExtended.h>
#include <LowPower.h>
#define wakePin 2
RTC_DS3231 rtc;
//-------------------------------------------------
void wakeUp() // here the interrupt is handled after wakeup
{
}
//------------------------------------------------------------
void setup() {
Serial.begin(9600);
delay(3000);
//imposta il PIN D2 per il wqakeup
pinMode(wakePin, INPUT);;
Wire.begin();
rtc.begin();
rtc.adjust(DateTime(__DATE__, __TIME__)); //imposta l'orologio in fase di compilazione col computer
//elimina allarmi eventualmente presenti
rtc.armAlarm(1, false);
rtc.clearAlarm(1);
rtc.alarmInterrupt(1, false);
rtc.armAlarm(2, false);
rtc.clearAlarm(2);
rtc.alarmInterrupt(2, false);
rtc.writeSqwPinMode(DS3231_OFF);
delay(1000);
Serial.println("Inizio");
}
//------------------------------------------------------------
void loop() {
DateTime now = rtc.now();
Serial.print(now.hour(),DEC);
Serial.print(":");
Serial.print(now.minute(),DEC);
Serial.print(":");
Serial.print(now.second(),DEC);
Serial.println();
//calcola la prossima ora di risveglio ovvero dopo un'ora
DateTime nextAlarm = now + TimeSpan(0, 1, 0, 0);
// l'ordine del timespan e' giorni,ore,minuti,secondi
rtc.setAlarm(ALM1_MATCH_HOURS, nextAlarm.minute(), nextAlarm.hour(), nextAlarm.second()); //imposta l'allarme
rtc.alarmInterrupt(1, true);
delay(3000); // wait for console
attachInterrupt(0, wakeUp, LOW);
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //entra in sleep su questa istruzione
detachInterrupt(0); //execution resumes from here after wake-up
//cancella la precedente impostazione dell'allarme 1
rtc.armAlarm(1, false);
rtc.clearAlarm(1);
rtc.alarmInterrupt(1, false);
delay(3000);
}
Addipresto Lanza
Era da tempo che volevo aggiungere alla mia collezione di regoli calcoatori una calcolatrice analogica per addizioni ma i prezzi su Ebay non sono trascurabili. Ieri ad un mercatino per 10 euro ho preso questa Addipresto Lanza completa del suo stilo originale perfettamente funzionante (a dire il vero sono strumenti cosi' semplici che e' difficile si rompano)
E' databile indicativamente seconda meta' degli anni 60 ed ha 7 rotori decimali. Non ha indicatore di overflow ma semplicemente il conteggio riparte da zero
Per effettuare una somma, per esempio 65+47 (come nel video sottostante). si procede puntando lo stilo sul numero delle unita' e ruotando verso il basso procedendo poi con il rotore delle decine. Inserito il primo addendo si ripete la procedura per il secondo per avere infine il risultato sul display in alto ovvero 112. Il reset e' effettuato con la levetta rossa
Le sottrazioni possono essere effettuate con i numeri in rosso come complemento a 9
Alcune informazioni sul meccanismo interno si possono ricavare a questo link
E' databile indicativamente seconda meta' degli anni 60 ed ha 7 rotori decimali. Non ha indicatore di overflow ma semplicemente il conteggio riparte da zero
Per effettuare una somma, per esempio 65+47 (come nel video sottostante). si procede puntando lo stilo sul numero delle unita' e ruotando verso il basso procedendo poi con il rotore delle decine. Inserito il primo addendo si ripete la procedura per il secondo per avere infine il risultato sul display in alto ovvero 112. Il reset e' effettuato con la levetta rossa
Le sottrazioni possono essere effettuate con i numeri in rosso come complemento a 9
Alcune informazioni sul meccanismo interno si possono ricavare a questo link
mercoledì 9 gennaio 2019
Cordova File Plugin per salvare file
questo esempio e' stato ripreso da questo esempio
si parte da zero
cordova create MyApp
cordova platform add android
cordova plugin add cordova-plugin-file
a questo punto e' stato creato il progetto base. Si apre Android Studio e si risolvono i vari errori di Gradle e poi si fa una prima build. In seguito si modificano i file come segue
Nella pagina html l'unico aspetto importante e' che siano importati cordova.js e /js/index.js
/assets/www/index.html
////////////////////////////////////////////////////////////
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Hello World</title>
</head>
<body onload="onLoad()">
<div class="app">
<h1>Apache Cordova</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
////////////////////////////////////////////////////////////
sull'evento deviceready si aggiunge quindi il codice evidenziato
/assets/www/js/index.js
///////////////////////////////////////////////////////////
var app = {
// Application Constructor
initialize: function() {
document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
},
// deviceready Event Handler
//
// Bind any cordova events here. Common events are:
// 'pause', 'resume', etc.
onDeviceReady: function() {
this.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
var fileName = 'myfile.txt'; // your file name
var data = '...'; // your data, could be useful JSON.stringify to convert an object to JSON string
window.resolveLocalFileSystemURL( cordova.file.externalRootDirectory, function( directoryEntry ) {
directoryEntry.getFile(fileName, { create: true }, function( fileEntry ) {
fileEntry.createWriter( function( fileWriter ) {
fileWriter.onwriteend = function( result ) {
console.log( 'pippoplutopaperino' );
};
fileWriter.onerror = function( error ) {
console.log( error );
};
fileWriter.write( data );
}, function( error ) { console.log( error ); } );
}, function( error ) { console.log( error ); } );
}, function( error ) { console.log( error ); } );
}
};
app.initialize();
///////////////////////////////////////////////////////////
si parte da zero
cordova create MyApp
cordova platform add android
cordova plugin add cordova-plugin-file
Nella pagina html l'unico aspetto importante e' che siano importati cordova.js e /js/index.js
/assets/www/index.html
////////////////////////////////////////////////////////////
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Hello World</title>
</head>
<body onload="onLoad()">
<div class="app">
<h1>Apache Cordova</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
////////////////////////////////////////////////////////////
sull'evento deviceready si aggiunge quindi il codice evidenziato
/assets/www/js/index.js
///////////////////////////////////////////////////////////
var app = {
// Application Constructor
initialize: function() {
document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
},
// deviceready Event Handler
//
// Bind any cordova events here. Common events are:
// 'pause', 'resume', etc.
onDeviceReady: function() {
this.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
var fileName = 'myfile.txt'; // your file name
var data = '...'; // your data, could be useful JSON.stringify to convert an object to JSON string
window.resolveLocalFileSystemURL( cordova.file.externalRootDirectory, function( directoryEntry ) {
directoryEntry.getFile(fileName, { create: true }, function( fileEntry ) {
fileEntry.createWriter( function( fileWriter ) {
fileWriter.onwriteend = function( result ) {
console.log( 'pippoplutopaperino' );
};
fileWriter.onerror = function( error ) {
console.log( error );
};
fileWriter.write( data );
}, function( error ) { console.log( error ); } );
}, function( error ) { console.log( error ); } );
}, function( error ) { console.log( error ); } );
}
};
app.initialize();
///////////////////////////////////////////////////////////
/res/config.xml
anche in questo file si modifica aggiungendo la parte evidenziata
///////////////////////////////////////////////////////////
<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.hellocordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<feature name="Whitelist">
<param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
<param name="onload" value="true" />
</feature>
<name>HelloCordova</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev@cordova.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<allow-intent href="market:*" />
<preference name="loglevel" value="DEBUG" />
<feature name="File">
<param name="android-package" value="org.apache.cordova.file.FileUtils" />
<param name="onload" value="true" />
</feature>
<allow-navigation href="cdvfile:*" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="files,cache, sdcard, cache-external, files-external" />
</widget>
<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.hellocordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<feature name="Whitelist">
<param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
<param name="onload" value="true" />
</feature>
<name>HelloCordova</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev@cordova.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<allow-intent href="market:*" />
<preference name="loglevel" value="DEBUG" />
<feature name="File">
<param name="android-package" value="org.apache.cordova.file.FileUtils" />
<param name="onload" value="true" />
</feature>
<allow-navigation href="cdvfile:*" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="files,cache, sdcard, cache-external, files-external" />
</widget>
///////////////////////////////////////////////////////////
se tutto e' andata a buon fine si trovera' il file myfile.txt nella cartella Documenti
se tutto e' andata a buon fine si trovera' il file myfile.txt nella cartella Documenti
martedì 8 gennaio 2019
Mandelbrot su Olivetti M10
Per la rubrica Retrocomputing Estremo insieme di Mandelbrot su Olivetti, splendido portatile del 1983 marcato Olivetti ma non prodotto da Olivetti, con un processore 8085 (dove il 5 sta per 5 Volt, non c'e' bisogno della doppia alimentazione 5-12V) a 2.4 MHz
25 minuti di calcolo per una griglia 64x44 con soglia di 20 cicli utilizzando Virtual T, un emulatore per Olivetti M10 e TRS-80
Il codice BASIC e' stato adattato partendo dalla base di Rosetta Code
Perche' ho usato un emulatore....non ho nella mia collezione un Olivetti M10??
Errato serial 40301385 24K perfettamente funzionate
25 minuti di calcolo per una griglia 64x44 con soglia di 20 cicli utilizzando Virtual T, un emulatore per Olivetti M10 e TRS-80
Il codice BASIC e' stato adattato partendo dalla base di Rosetta Code
Perche' ho usato un emulatore....non ho nella mia collezione un Olivetti M10??
Errato serial 40301385 24K perfettamente funzionate
lunedì 7 gennaio 2019
Interagire con DynamoDB con Lambda e API Gateway
Un sistema per interagire con DynamoDB mediante una funzione Lambda triggerata da API Gateway
Prima prima cosa ho creato a mano una tabella in DynamoDB con due colonne nome (stringa) ed indice (numerico)
La funzione Lambda per interagire con DynamoDB necessita di permessi. Per rendere le cose piu' semplici ho usato i permessi piu' estesi che corrispondono al ruolo AmazonDyamoDBFullAccess (per creare il ruolo si va in consolle di AWS, si apre IAM, Ruolo, Crea Ruolo, si selezione il servizio Lambda e si spunta AmazonDyamoDBFullAccess) Dopo aver salvato il ruolo con un nome si modifica il Ruolo di Esecuzione nella finestra della funzione Lambda impostando il nuovo ruolo
La funzione Lambda di seguito mostra un insertItem ed un getItem condizionato al valore dell'indice numerico
================================================
var AWS = require('aws-sdk');
var DOC = require('dynamodb-doc');
var dynamo = new DOC.DynamoDB();
exports.handler = function(event, context) {
var tableName = "bollettini";
var item = {
nome: "Federico",
indice: Number(4)
}
var params = {
TableName: tableName,
Item: item
};
dynamo.putItem(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
var cb = function(err, data) {
if(err) {
console.log('error getItem: ',err);
context.done('Unable to getItem', null);
} else {
if(data.Item && data.Item.nome) {
context.done(null, data.Item);
} else {
context.done(null, {});
}
}
};
dynamo.getItem({TableName:"bollettini", Key:{indice:2}}, cb);
};
Prima prima cosa ho creato a mano una tabella in DynamoDB con due colonne nome (stringa) ed indice (numerico)
La funzione Lambda per interagire con DynamoDB necessita di permessi. Per rendere le cose piu' semplici ho usato i permessi piu' estesi che corrispondono al ruolo AmazonDyamoDBFullAccess (per creare il ruolo si va in consolle di AWS, si apre IAM, Ruolo, Crea Ruolo, si selezione il servizio Lambda e si spunta AmazonDyamoDBFullAccess) Dopo aver salvato il ruolo con un nome si modifica il Ruolo di Esecuzione nella finestra della funzione Lambda impostando il nuovo ruolo
La funzione Lambda di seguito mostra un insertItem ed un getItem condizionato al valore dell'indice numerico
================================================
var AWS = require('aws-sdk');
var DOC = require('dynamodb-doc');
var dynamo = new DOC.DynamoDB();
exports.handler = function(event, context) {
var tableName = "bollettini";
var item = {
nome: "Federico",
indice: Number(4)
}
var params = {
TableName: tableName,
Item: item
};
dynamo.putItem(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
var cb = function(err, data) {
if(err) {
console.log('error getItem: ',err);
context.done('Unable to getItem', null);
} else {
if(data.Item && data.Item.nome) {
context.done(null, data.Item);
} else {
context.done(null, {});
}
}
};
dynamo.getItem({TableName:"bollettini", Key:{indice:2}}, cb);
};
================================================
A questo punto per eseguire la Lambda e' necessario impostare un trigger che nel mio caso e' API Gateway. Dalla consolle di AWS si sceglie API Gateway, si selezione Create API, si indica il nome, Nella pagina successiva si clicca sul menu' a tendina Actions e si sceglie GET. Si apre una pagina sulla destra in si inserisce l'ARN della Lambda e si salva. A questo punto si pubblica la API e si avra' come risposta un link del tipo https:/xxxxxxxx.execute-api.eu-west-1.amazonaws.com/test/
Puntano il browser al link indicato si mettera' in esecuzione la funzione Lambda
Iscriviti a:
Post (Atom)
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...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...
-
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 riferiment...