Passatempo da quarantena....comprato due anni fa ma mai avuto il tempo nemmeno di iniziarlo
lunedì 13 aprile 2020
Da Arduino ad Internet tramite Android
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
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);
}
=========================================================
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);
}
=========================================================
I dati sono plottati sul server mediante JSCanvas. Gli script si trovano qui https://github.com/c1p81/Seriale/tree/master/app/seriale_html
venerdì 10 aprile 2020
Trasmissione dati con ultrasuoni
Leggendo le caratteristiche di Arduino Nano 33 BLE ho scoperto che era compatibile con la trasmissione dati via ultrasuoni tramite le librerie CHIRP. La ditta pero' e' stata acquisita da Sonos e non e' piu' possibile usare le librerie per l'impossibilita' di acquisire la API KEY.
Ho scoperto che si puo' fare qualche test anche con un semplice browser (meglio Chrome) usando le librerie Quiet JS puntando a questa pagina https://quiet.github.io/quiet-js/
La cosa divertente e' che mio figlio di 10 anni sente distintamente la frequenza agli ultrasuoni mentre io no (questa predisposizione dei bambini a sentire gli ultrasuoni l'ho vista usare da un prestigiatore per un trucco magico che prevedeva la collaborazione del figlio..... in pratica il figlio indovinava sempre la carta nascosta ma solo perche' il padre con emettitore indicava il valore della carta con un codice condiviso)
Ho scoperto che si puo' fare qualche test anche con un semplice browser (meglio Chrome) usando le librerie Quiet JS puntando a questa pagina https://quiet.github.io/quiet-js/
La cosa divertente e' che mio figlio di 10 anni sente distintamente la frequenza agli ultrasuoni mentre io no (questa predisposizione dei bambini a sentire gli ultrasuoni l'ho vista usare da un prestigiatore per un trucco magico che prevedeva la collaborazione del figlio..... in pratica il figlio indovinava sempre la carta nascosta ma solo perche' il padre con emettitore indicava il valore della carta con un codice condiviso)
QML Mandelbrot in UBPorts / Ubuntu Touch (2)
Avevo gia' provato qui a creare l'insieme di Mandelbrot su UBPorts in QML ma il programma era scandalosamente lento ed ho provato a migliorare
==============================================================
/*
* Copyright (C) 2020 Luca Innocenit
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-calculator-app is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import Ubuntu.Components 1.3
//import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0
import QtQuick.Window 2.2
MainView {
id: root
objectName: 'mainView'
applicationName: 'qtcpp.com.luca.innocenti'
automaticOrientation: true
visible: true
width: Screen.width
height: Screen.width
Canvas {
id: mycanvas
anchors.centerIn: parent
width: Screen.width
height: Screen.width
onPaint: {
console.log("width "+ width.toString())
console.log("height "+ height.toString())
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(0, 0, 0, 1);
ctx.fillRect(0, 0, width, height);
var imgData = ctx.createImageData(height, width);
////////
var re_min = -2.0;
var im_min = -1.2;
var re_max = 0.7;
var im_max = 1.2;
var iterazioni = 50;
var r;
var a,b;
var x,y,x_new,y_new;
var test;
var re_factor = (re_max-re_min);
var im_factor = (im_max-im_min);
var indice = 0;
for (var i=0;i<width;i++)
{
for (var j=0;j<height;j++)
{
a = re_min+(j*re_factor/height);
b = im_min+(i*im_factor/width);
x = 0;
y = 0;
test = 0;
imgData.data[indice+3]= 255;
//console.log(indice)
for (var k=0;k<iterazioni;k++)
{
x_new = (x*x)-(y*y)+a;
y_new = (2*x*y)+b;
if (((x_new*x_new)+(y_new*y_new))>4)
{
if (k%2)
{
// colora il punto
imgData.data[indice]=255;
imgData.data[indice+1]=255;
imgData.data[indice+2]=255;
}
break;
}
x = x_new;
y = y_new;
}
indice = indice + 4;
}
}
///////
console.log("terminato")
ctx.drawImage(imgData, 0, 0);
}
}
}
In questo codice il risultato di calcolo per ogni pixel viene salvato in un array imgData che poi
trasferito in un colpo sul Canvas. In questo modo il tempo di calcolo e' divenuto inferiore ad un terzo di quello della precedente prova
/*
* Copyright (C) 2020 Luca Innocenit
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* ubuntu-calculator-app is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import Ubuntu.Components 1.3
//import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0
import QtQuick.Window 2.2
MainView {
id: root
objectName: 'mainView'
applicationName: 'qtcpp.com.luca.innocenti'
automaticOrientation: true
visible: true
width: Screen.width
height: Screen.width
Canvas {
id: mycanvas
anchors.centerIn: parent
width: Screen.width
height: Screen.width
onPaint: {
console.log("width "+ width.toString())
console.log("height "+ height.toString())
var ctx = getContext("2d");
ctx.fillStyle = Qt.rgba(0, 0, 0, 1);
ctx.fillRect(0, 0, width, height);
var imgData = ctx.createImageData(height, width);
////////
var re_min = -2.0;
var im_min = -1.2;
var re_max = 0.7;
var im_max = 1.2;
var iterazioni = 50;
var r;
var a,b;
var x,y,x_new,y_new;
var test;
var re_factor = (re_max-re_min);
var im_factor = (im_max-im_min);
var indice = 0;
for (var i=0;i<width;i++)
{
for (var j=0;j<height;j++)
{
a = re_min+(j*re_factor/height);
b = im_min+(i*im_factor/width);
x = 0;
y = 0;
test = 0;
imgData.data[indice+3]= 255;
//console.log(indice)
for (var k=0;k<iterazioni;k++)
{
x_new = (x*x)-(y*y)+a;
y_new = (2*x*y)+b;
if (((x_new*x_new)+(y_new*y_new))>4)
{
if (k%2)
{
// colora il punto
imgData.data[indice]=255;
imgData.data[indice+1]=255;
imgData.data[indice+2]=255;
}
break;
}
x = x_new;
y = y_new;
}
indice = indice + 4;
}
}
///////
console.log("terminato")
ctx.drawImage(imgData, 0, 0);
}
}
}
giovedì 9 aprile 2020
Alpine su Getac M230
Volevo ridare vita a questo GETAC M230, una macchina con un core duo. Il problema e' che questa macchina non ha una porta ethernet (c'e' una scheda di rete per fibra ottica) e non volevo impazzire a caricare i driver da USB della WiFi in fase di installazione come accade per Debian
Ho provato prima una LUbuntu che oggettivamente ha reso la macchina inservibile. Sono passato quindi ad Alpine Linux i386 che ha riconosciuto la scheda WiFi al volo
Avevo gia' configurato una Alpine
apk add wireless-tools wpa_supplicant
Uno dei problemi e' che al riavvio non viene agganciato l'accesso point al boot.
Ogni volta devo rilanciare questi comandi per ottenre la connessione di rete
wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant_wpa_supplicant.conf
udhcpc -i wlan0
Per montare i3 window manager si devono aggiungere i pacchetti
apk add i3wm
apk add i3lock i3status
apk add xterm
e si edita il file .xinitrc
==========================
DEFAULT=13
[ -n $1 ] && 1
exec ${DEFAULT}
==========================
I3 funziona al meglio in modalita' tabbed
Per avere il controllo della batteria si deve aggiungere il supporto ACPI
apk add acpi
Firefox si installa e funziona ma freeza spesso
Non e' presente Emacs per X, c'e' solo per la consolle in quanto il sistema e' basato su uclib e non glibc. In compenso c'e' una vetusta versione di Qt/ Qt Creator
Per spengere la macchina si deve digitare
poweroff
Ho provato prima una LUbuntu che oggettivamente ha reso la macchina inservibile. Sono passato quindi ad Alpine Linux i386 che ha riconosciuto la scheda WiFi al volo
Avevo gia' configurato una Alpine
apk add wireless-tools wpa_supplicant
Ingresso fibra ottica |
apk add wireless-tools wpa_supplicant
Uno dei problemi e' che al riavvio non viene agganciato l'accesso point al boot.
Ogni volta devo rilanciare questi comandi per ottenre la connessione di rete
wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant_wpa_supplicant.conf
udhcpc -i wlan0
Per montare i3 window manager si devono aggiungere i pacchetti
apk add i3wm
apk add i3lock i3status
apk add xterm
e si edita il file .xinitrc
==========================
DEFAULT=13
[ -n $1 ] && 1
exec ${DEFAULT}
==========================
I3 funziona al meglio in modalita' tabbed
Per avere il controllo della batteria si deve aggiungere il supporto ACPI
apk add acpi
Firefox si installa e funziona ma freeza spesso
Non e' presente Emacs per X, c'e' solo per la consolle in quanto il sistema e' basato su uclib e non glibc. In compenso c'e' una vetusta versione di Qt/ Qt Creator
Per spengere la macchina si deve digitare
poweroff
mercoledì 8 aprile 2020
Android Studio WiFi Adb Plugin
Per programmare con Adb via WiFi si puo' fare in vari modi
Usando un plugin (la via piu' comoda) si puo' installare un plugin di Android Studio da File/Settings/Plugins e scegliendo per esempio Android WiFi ADB
Si aggiungera' una icona (in verde chiaro al centro nell'immagine successiva)
Si collega il telefono via USB agganciandosi alla stessa WiFi del portatile. Si clicca sull'icona, si attende la connessione e successivamente si puo' disconnettere il cavo USB
Altrimenti da shell si possono inviare i seguenti comandi
A cavo USB attaccato si digita
adb shell setprop service.adb.tcp.port 4444
Usando un plugin (la via piu' comoda) si puo' installare un plugin di Android Studio da File/Settings/Plugins e scegliendo per esempio Android WiFi ADB
Si collega il telefono via USB agganciandosi alla stessa WiFi del portatile. Si clicca sull'icona, si attende la connessione e successivamente si puo' disconnettere il cavo USB
Altrimenti da shell si possono inviare i seguenti comandi
A cavo USB attaccato si digita
adb tcpip 4444
adb connect ip_telefono:4444
adb connect ip_telefono:4444
OkHttp per Android
Per utilizzare chiamate HTTP in un progetto Android basato su Java (per Kotlin una libreria comoda e' Fuel ) si puo' utilizzare OKHttp anche se e' cosi' immediato utilizzarla
Per aggiungere la libreria al progetto si edita build.gradle(progetto) aggiugendo la riga in giallo
e si aggiunge la libreria indicata dalla riga in giallo
Per prima cosa si aggiunge il permesso di accesso ad Internet nel Manifest
In seguito si crea un directory xml in res e si crea un nuovo file XML denominato network_security_config.xml con i permessi di accesso alla rete
Per esempio qui si abilita il traffico HTTP (HTTPS e' default) verso tutti i domini
network_security_config.xml
-----------------------------------------
Si torna al Manifest e si aggiunge la riga in giallo
Per aggiungere la libreria al progetto si edita build.gradle(progetto) aggiugendo la riga in giallo
allprojects { repositories { google() jcenter() maven { url "https://jitpack.io" } }}
e si aggiunge la libreria indicata dalla riga in giallo
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'com.github.felHR85:UsbSerial:6.1.0' implementation("com.squareup.okhttp3:okhttp:4.5.0")}
Per prima cosa si aggiunge il permesso di accesso ad Internet nel Manifest
<uses-permission android:name="android.permission.INTERNET" />
In seguito si crea un directory xml in res e si crea un nuovo file XML denominato network_security_config.xml con i permessi di accesso alla rete
Per esempio qui si abilita il traffico HTTP (HTTPS e' default) verso tutti i domini
network_security_config.xml
-----------------------------------------
<?xml version="1.0" encoding="utf-8"?><network-security-config xmlns:android="http://schemas.android.com/apk/res/android"> <base-config cleartextTrafficPermitted="true" /> </network-security-config>-----------------------------------------
Si torna al Manifest e si aggiunge la riga in giallo
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true"
il metodo standard per implementare la chiamata e' creare una classe
public static class senddata { OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } } }
e poi chiamare il metodo per esempio in GET
senddata invio = new senddata();try { String response = invio.run("http://XXX.XXXX.XXX.XXX/seriale/index.php?stringa="+data.toString()+"&batteria="+percentage);} catch (IOException e) { e.printStackTrace();}
Iscriviti a:
Post (Atom)
Change Detection with structural similarity
L'idea di base e' quella di cercare le differenze tra le due immagini sottostanti Non e' immediatamente visibile ma ci sono dei ...
-
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...
-
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...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...