Nido, forse di passero, caduto a terra
lunedì 30 maggio 2016
giovedì 26 maggio 2016
Bossac: extra argument found su IDE Arduino Due
E' un po ' di tempo che non usavo Arduino Due ed la proma novita' e che per compilare i programmi nella IDE 1.6.8 si devono scaricare le definizioni della scheda da Strumenti/Scheda/Gestore Scheda selezionando Arduino SAM Boards 32 bits ARM Cortex-M3
Una volta modificato in questo modo l'ambiente di sviluppo ho provato a compilare uno sketch ma sia su Windows che Linux compariva lo stesso messaggio
bossac : extra argument found
il problema risiede nello switch w e si risolve andando nel file
/home/linnocenti/.arduino15/packages/arduino/hardware/sam/1.6.8/platform.txt
si va quindi alla riga 106 e si elimina dopo -w il codice {upload.verify}. La riga corretta e' la seguente
tools.bossac.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -U {upload.native_usb} -e -w -b "{build.path}/{build.project_name}.bin" -R
in questo modo la compilazione arriva al termine correttamente
Una volta modificato in questo modo l'ambiente di sviluppo ho provato a compilare uno sketch ma sia su Windows che Linux compariva lo stesso messaggio
bossac : extra argument found
il problema risiede nello switch w e si risolve andando nel file
/home/linnocenti/.arduino15/packages/arduino/hardware/sam/1.6.8/platform.txt
si va quindi alla riga 106 e si elimina dopo -w il codice {upload.verify}. La riga corretta e' la seguente
tools.bossac.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -U {upload.native_usb} -e -w -b "{build.path}/{build.project_name}.bin" -R
in questo modo la compilazione arriva al termine correttamente
mercoledì 25 maggio 2016
Troubleshooting Mysql
Questa volta sono stato contattato perche' un server, che in passato ho montato ed amministrato direttamente per un annetto, aveva iniziato a fare le bizze.
Una rapida occhiata con htop ha mostrato che la macchina era in picco con il processore tra 85% e 100% e con tutti i processi principali occupati da Mysql
Una volta capito il responsabile c'era da capire il motivo. Il primo sospetto, visto il tempo di esecuzione di ogni processo, era che le query fossero talmente lunghe e frequenti da sovrapporsi nel tempo da creare un effetto a cascata che rendeva dopo un po' il tempo il server non utilizzabile
Per definire il problema ho usato il comando
| Id | User | Host | db | Command | Time | State | Info | Progress |
+-------+----------------------+--------------------------+--------+---------+------+----------------------+------------------------------------------------------------------------------------------------------+----------+
| 12296 | utente | localhost | db | Query | 2 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 12299 | utente | localhost | db | Query | 16 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 12303 | utente | localhost | db | Query | 4 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 12308 | utente | localhost | db | Query | 33 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13392 | utente | localhost | db | Query | 35 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13396 | utente | localhost | db | Query | 11 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13399 | utente | localhost | db | Query | 5 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13403 | utente | localhost | db | Query | 26 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13411 | utente | localhost | db | Query | 40 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 14407 | utente | localhost | db | Query | 45 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 14411 | utente | localhost | db | Query | 54 | Sending data | SELECT AVG(VAL) AS VAL
------------------------------------------------------------------------
ovviamente un traffico che ha messo in ginocchio il server.
Un metodo alternativo e' quello di installare mytop (un clone del comando top specifico per MySql)
Il comando si puo' lanciare passando i parametri da file di configurazione oppure tramite switch sulla linea di comando. Ho usato la seconda strada
mytop -u root -d databasename --prompt
(e' necessario inserire il nome del database, non accetta il monitoraggio di tutti i db)
In questa modalita' vengono mostrate le query per secondo e le query lente con il traffico di rete
Una rapida occhiata con htop ha mostrato che la macchina era in picco con il processore tra 85% e 100% e con tutti i processi principali occupati da Mysql
Htop |
Una volta capito il responsabile c'era da capire il motivo. Il primo sospetto, visto il tempo di esecuzione di ogni processo, era che le query fossero talmente lunghe e frequenti da sovrapporsi nel tempo da creare un effetto a cascata che rendeva dopo un po' il tempo il server non utilizzabile
Per definire il problema ho usato il comando
mysqladmin -u root -p -i 1 processlist
in questo modo si ottiene una lista dei processi in corso sul server MySql evidenziando anche la query ed il tempo di esecuzione di ciascuna query.
In questo modo si ottiene una lista dei processi in corso sul server Mysql evidenziando anche la query in corso ed il tempo di esecuzione. Impostando il parametro i ad 1 si ottiene i dati relativi ad 1 secondo di tempo. Nel parziale listato si e' visto che in un secondo venivano eseguite oltre 120 query complesse con il tempo in secondo impiegato da ciascun thread
------------------------------------------------------------------------
+-------+----------------------+--------------------------+--------+---------+------+----------------------+------------------------------------------------------------------------------------------------------+----------+| Id | User | Host | db | Command | Time | State | Info | Progress |
+-------+----------------------+--------------------------+--------+---------+------+----------------------+------------------------------------------------------------------------------------------------------+----------+
| 12296 | utente | localhost | db | Query | 2 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 12299 | utente | localhost | db | Query | 16 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 12303 | utente | localhost | db | Query | 4 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 12308 | utente | localhost | db | Query | 33 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.f
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13392 | utente | localhost | db | Query | 35 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13396 | utente | localhost | db | Query | 11 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13399 | utente | localhost | db | Query | 5 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13403 | utente | localhost | db | Query | 26 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 13411 | utente | localhost | db | Query | 40 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 14407 | utente | localhost | db | Query | 45 | Sending data | SELECT AVG(VAL) AS VAL
FROM db.E
WHERE NET = (SELECT NET.NET_ID
| 0.000 |
| 14411 | utente | localhost | db | Query | 54 | Sending data | SELECT AVG(VAL) AS VAL
------------------------------------------------------------------------
ovviamente un traffico che ha messo in ginocchio il server.
Un metodo alternativo e' quello di installare mytop (un clone del comando top specifico per MySql)
Il comando si puo' lanciare passando i parametri da file di configurazione oppure tramite switch sulla linea di comando. Ho usato la seconda strada
mytop -u root -d databasename --prompt
(e' necessario inserire il nome del database, non accetta il monitoraggio di tutti i db)
Mytop del server quando sono state interrotte le query lunghe |
lunedì 23 maggio 2016
Shodan
Shodan.io e' un sito web che propone un database di indirizzi di dispositivi IOT che sono esposti su IP pubblici. La ricerca puo' essere fatta in modo geografico (per esempio city:Florence, country:"IT", con le coordinate geografiche mediante geo:42.9693,-74.1224 ) oppure con dati derivanti per servizi esposti (port:443 per esempio) e sistema operativo (os:linux) o network (net:150.xxx.xxx.xxx/16)
Le query si possono eseguire anche senza da URL con per esempio http://www.shodanhq.com/search?q=port%3A5632 ma per le query avanzate e' necessario essere loggati
Non e' niente che non si possa fare anche tramite Google ma e' sicuramente un sistema piu' semplice e speditivo. Con uno strumento del genere ovviamente si puo' giocare oppure fare danni (mirando delle macchine con vulnerabilita'). La cosa ancora piu' strana e' che ci sia qualcuno che espone su Internet con indirizzi pubblici dei dispositivi privi di password o con credenziali di default
Giusto per vedere se la cosa funziona ho provato a cercare delle webcam.
Nell'ultimo caso sono incappato in una camera con il sistema di amministrazione ed i comandi PTZ perfettamente accessibili, probabilmente una camera Maygion o simile. Ovviamente sono uscito senza fare danni ma per esperienza,avendo anche la possibilita' di modificare il firmware, avrei potuto rendere inservibile il sistema.
ps. non mi e'stato possibile rintracciare il proprietario della camera per avvisarlo.
Le query si possono eseguire anche senza da URL con per esempio http://www.shodanhq.com/search?q=port%3A5632 ma per le query avanzate e' necessario essere loggati
Non e' niente che non si possa fare anche tramite Google ma e' sicuramente un sistema piu' semplice e speditivo. Con uno strumento del genere ovviamente si puo' giocare oppure fare danni (mirando delle macchine con vulnerabilita'). La cosa ancora piu' strana e' che ci sia qualcuno che espone su Internet con indirizzi pubblici dei dispositivi privi di password o con credenziali di default
Giusto per vedere se la cosa funziona ho provato a cercare delle webcam.
Schermata di amministrazione |
Webcam |
ps. non mi e'stato possibile rintracciare il proprietario della camera per avvisarlo.
venerdì 20 maggio 2016
Track Object con OpenCv ed IPCamera PTZ in realtime
L'idea alla base di questo post e' quella di usare OpenCV per riconoscere un oggetto in stream video da una IP camera dotata di movimento PTZ in modo che l'oggetto rimanga sempre al centro dell'inquadratura
Come camera ho ripreso la Maygion (gia' vista qui, un modello piuttosto vecchiotto da 0.3MPx) e l'oggetto da tracciare era la scatola a sinistra
Tramite OpenCV viene catturato lo stream video della camera IP, l'immagine viene elaborato alla ricerca del colore verde calcolando il centroide, a questo punto si calcola la posizione del centroide rispetto al centro dell'immagine e si pilota la camera per posizionare il centroide piu' vicino possibile al centro dell'immagine.
Questo e' il video della prova
Per rendere le cose piu' semplici, in questo primo esempio viene mostrato come catturato il flusso derivante dalla camera Ip mediante OpenCV. Di fatto il sistema e' praticamente a quello che si applica ad una webcam con la sola differenza che si deve passare l'url dello stream (variabile da produttore a produttore e da modello a modello)
---------------------------------------------
import numpy as np
import cv2
vcap = cv2.VideoCapture("http://192.168.43.207:81/videostream.cgi?stream=0&usr=admin&pwd=admin")
if vcap.isOpened():
rval,frame = vcap.read()
print "acquisito"
else:
rval = False
print "non acquisito"
while rval:
cv2.imshow("preview",frame)
rval,frame = vcap.read()
key = cv2.waitKey(20)
if key == 27:
break
cv2.destroyWindow("preview")
---------------------------------------------
Questo e' invece il codice per pilotare il movimento della camera (in pratica si mandano comandi via stringa http)
---------------------------------------------
import time
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ur = "http://192.168.43.207:81/"
direzione = "up"
html=urlopen(ur+"moveptz.xml?dir="+direzione+"&user=admin&password=admin")
time.sleep(0.1)
html=urlopen(ur+"moveptz.xml?dir=stop&user=admin&password=admin")
---------------------------------------------
Per tracciare il movimento della sagoma verde ho ripreso, modificandolo leggermente, questo esempio di Conan Zhao and Simon D. Levy
---------------------------------------------
import cv2
import numpy as np
import time
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ur = "http://192.168.43.207:81/"
# For OpenCV2 image display
WINDOW_NAME = 'GreenBallTracker'
def track(image):
# Blur the image to reduce noise
blur = cv2.GaussianBlur(image, (5,5),0)
# Convert BGR to HSV
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
# Threshold the HSV image for only green colors
lower_green = np.array([40,70,70])
upper_green = np.array([80,200,200])
# Threshold the HSV image to get only green colors
mask = cv2.inRange(hsv, lower_green, upper_green)
# Blur the mask
bmask = cv2.GaussianBlur(mask, (5,5),0)
# Take the moments to get the centroid
moments = cv2.moments(bmask)
m00 = moments['m00']
centroid_x, centroid_y = None, None
if m00 != 0:
centroid_x = int(moments['m10']/m00)
centroid_y = int(moments['m01']/m00)
# Assume no centroid
ctr = (-1,-1)
# Use centroid if it exists
if centroid_x != None and centroid_y != None:
ctr = (centroid_x, centroid_y)
# Put black circle in at centroid in image
cv2.circle(image, ctr, 4, (255,0,0))
x_schermo = centroid_x-320
y_schermo = centroid_x-240
print "X="+str(x_schermo) + " ; Y=" + str(y_schermo)
tempo = 0.02
if (x_schermo > 0):
html=urlopen(ur+"moveptz.xml?dir=left&user=admin&password=admin")
time.sleep(tempo)
html=urlopen(ur+"moveptz.xml?dir=stop&user=admin&password=admin")
else:
html=urlopen(ur+"moveptz.xml?dir=right&user=admin&password=admin")
time.sleep(tempo)
html=urlopen(ur+"moveptz.xml?dir=stop&user=admin&password=admin")
# Display full-color image
cv2.imshow(WINDOW_NAME, image)
# Force image display, setting centroid to None on ESC key input
if cv2.waitKey(1) & 0xFF == 27:
ctr = None
# Return coordinates of centroid
return ctr
# Test with input from camera
if __name__ == '__main__':
capture = cv2.VideoCapture(ur+"videostream.cgi?stream=0&usr=admin&pwd=admin")
while True:
okay, image = capture.read()
if okay:
if not track(image):
break
if cv2.waitKey(1) & 0xFF == 27:
break
else:
print('Capture failed')
break
---------------------------------------------
Come camera ho ripreso la Maygion (gia' vista qui, un modello piuttosto vecchiotto da 0.3MPx) e l'oggetto da tracciare era la scatola a sinistra
Tramite OpenCV viene catturato lo stream video della camera IP, l'immagine viene elaborato alla ricerca del colore verde calcolando il centroide, a questo punto si calcola la posizione del centroide rispetto al centro dell'immagine e si pilota la camera per posizionare il centroide piu' vicino possibile al centro dell'immagine.
Questo e' il video della prova
---------------------------------------------
import numpy as np
import cv2
vcap = cv2.VideoCapture("http://192.168.43.207:81/videostream.cgi?stream=0&usr=admin&pwd=admin")
if vcap.isOpened():
rval,frame = vcap.read()
print "acquisito"
else:
rval = False
print "non acquisito"
while rval:
cv2.imshow("preview",frame)
rval,frame = vcap.read()
key = cv2.waitKey(20)
if key == 27:
break
cv2.destroyWindow("preview")
---------------------------------------------
Questo e' invece il codice per pilotare il movimento della camera (in pratica si mandano comandi via stringa http)
---------------------------------------------
import time
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ur = "http://192.168.43.207:81/"
direzione = "up"
html=urlopen(ur+"moveptz.xml?dir="+direzione+"&user=admin&password=admin")
time.sleep(0.1)
html=urlopen(ur+"moveptz.xml?dir=stop&user=admin&password=admin")
---------------------------------------------
Per tracciare il movimento della sagoma verde ho ripreso, modificandolo leggermente, questo esempio di Conan Zhao and Simon D. Levy
---------------------------------------------
import cv2
import numpy as np
import time
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ur = "http://192.168.43.207:81/"
# For OpenCV2 image display
WINDOW_NAME = 'GreenBallTracker'
def track(image):
# Blur the image to reduce noise
blur = cv2.GaussianBlur(image, (5,5),0)
# Convert BGR to HSV
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
# Threshold the HSV image for only green colors
lower_green = np.array([40,70,70])
upper_green = np.array([80,200,200])
# Threshold the HSV image to get only green colors
mask = cv2.inRange(hsv, lower_green, upper_green)
# Blur the mask
bmask = cv2.GaussianBlur(mask, (5,5),0)
# Take the moments to get the centroid
moments = cv2.moments(bmask)
m00 = moments['m00']
centroid_x, centroid_y = None, None
if m00 != 0:
centroid_x = int(moments['m10']/m00)
centroid_y = int(moments['m01']/m00)
# Assume no centroid
ctr = (-1,-1)
# Use centroid if it exists
if centroid_x != None and centroid_y != None:
ctr = (centroid_x, centroid_y)
# Put black circle in at centroid in image
cv2.circle(image, ctr, 4, (255,0,0))
x_schermo = centroid_x-320
y_schermo = centroid_x-240
print "X="+str(x_schermo) + " ; Y=" + str(y_schermo)
tempo = 0.02
if (x_schermo > 0):
html=urlopen(ur+"moveptz.xml?dir=left&user=admin&password=admin")
time.sleep(tempo)
html=urlopen(ur+"moveptz.xml?dir=stop&user=admin&password=admin")
else:
html=urlopen(ur+"moveptz.xml?dir=right&user=admin&password=admin")
time.sleep(tempo)
html=urlopen(ur+"moveptz.xml?dir=stop&user=admin&password=admin")
# Display full-color image
cv2.imshow(WINDOW_NAME, image)
# Force image display, setting centroid to None on ESC key input
if cv2.waitKey(1) & 0xFF == 27:
ctr = None
# Return coordinates of centroid
return ctr
# Test with input from camera
if __name__ == '__main__':
capture = cv2.VideoCapture(ur+"videostream.cgi?stream=0&usr=admin&pwd=admin")
while True:
okay, image = capture.read()
if okay:
if not track(image):
break
if cv2.waitKey(1) & 0xFF == 27:
break
else:
print('Capture failed')
break
---------------------------------------------
giovedì 19 maggio 2016
LCD 3.2 " Waveshare su Raspberry
Ho provato uno schermo LCD da 3.2 pollici per Raspberry da montare direttamente sul connettore a 40 pin.
Se si prova ad usare una Raspbian pura il risultato e' il seguente.. nessuna immagine tranne lo schermo bianco
Il problema e' che lo schermo comunica con la Raspberry tramite SPI e su Raspbian di default non e' montato il modulo per gestire lo schermo. Su Waveshare sono presenti tutte le istruzioni passo passo per compilare il modulo e montarlo ma la soluzione piu' diretta e' scaricarsi una distribuzione Raspbian gia' modificata
Lo schermo ha una risoluzione di 320x240 ed una volta avviato X si vede che le finestre sono tutte piu' grandi di questa dimensioni. La soluzione per spostare l'area di visualizzazione e' quella di cliccare sinistro tenendo premuto il tasto Alt. In questo modo si puo' trascinare la finestra
Riducendo poi il font di default di X e di XTerm si riesce "quasi" a lavorarci
Con la Raspbian gia' modificata e' gia' montato anche il modulo per il touchscreen per cui e' possibile utilizzare il Raspberry con il pennino (in dotazione) od anche con le dita.In alto e' disponibile una tastiera virtuale ma e' veramente difficile usarla
Sulla sinistra dello schermo sono presenti tre pulsanti che sono connessi ai pin GPIO 12,16 e 18
Per completezza il dispositivo dello schermo si trova su /dev/fb1
Se si prova ad usare una Raspbian pura il risultato e' il seguente.. nessuna immagine tranne lo schermo bianco
Il problema e' che lo schermo comunica con la Raspberry tramite SPI e su Raspbian di default non e' montato il modulo per gestire lo schermo. Su Waveshare sono presenti tutte le istruzioni passo passo per compilare il modulo e montarlo ma la soluzione piu' diretta e' scaricarsi una distribuzione Raspbian gia' modificata
Lo schermo ha una risoluzione di 320x240 ed una volta avviato X si vede che le finestre sono tutte piu' grandi di questa dimensioni. La soluzione per spostare l'area di visualizzazione e' quella di cliccare sinistro tenendo premuto il tasto Alt. In questo modo si puo' trascinare la finestra
Con la Raspbian gia' modificata e' gia' montato anche il modulo per il touchscreen per cui e' possibile utilizzare il Raspberry con il pennino (in dotazione) od anche con le dita.In alto e' disponibile una tastiera virtuale ma e' veramente difficile usarla
Sulla sinistra dello schermo sono presenti tre pulsanti che sono connessi ai pin GPIO 12,16 e 18
Per completezza il dispositivo dello schermo si trova su /dev/fb1
Ripulire perdita di liquido da batterie / pile
Capita ogni tanto di scordarsi le batterie all'interno di un dispositivo e poi di trovare la sopresa della perdita del liquido interno con la formazione di un materiale biancastro che avvolge i contatti e la batteria stessa.
La cosa si fa tremenda quando il materiale impedisce l'uscita della batteria stessa, come nel caso in foto
Una soluzione molto semplice e funzionante e' quella di usare l'aceto da cucina. Si sviluppa una reazione tra l'acido acetico e la patina che genera una effervescenza e che di fatto libera la pila e pulisce i contatti
Dal punto di vista strettamente chimico non saprei bene come funziona la cosa. Il reagente contenenuto nell'aceto e' sicuramente l'acido acetico. Su alcuni siti indicano che il materiale bianco e' idrossido di potassio (per pile alcaline) ma la reazione (ripresa da qui) produce acqua e non gas per cui non e' quello che ho visto io
NaOH(aq) + CH3COOH(aq) → CH3COONa(aq) + H2O(l)
Insomma, non so perche' ma decisamente funziona
Ho provato lo stesso sistema su una vecchia calcolatrice Casio di fine anni 70. In questo caso l'ossido si presenta di colore verde rame (non so se e' il colore del contatto ossidato od il colore di quanto fuoriuscito dalla batteria). I contatti si presentano fortemente corrosi
In questo caso il sistema dell'aceto non funziona. Credo che in quel periodo si usassero pile con composizione differente
La cosa si fa tremenda quando il materiale impedisce l'uscita della batteria stessa, come nel caso in foto
Una soluzione molto semplice e funzionante e' quella di usare l'aceto da cucina. Si sviluppa una reazione tra l'acido acetico e la patina che genera una effervescenza e che di fatto libera la pila e pulisce i contatti
Dal punto di vista strettamente chimico non saprei bene come funziona la cosa. Il reagente contenenuto nell'aceto e' sicuramente l'acido acetico. Su alcuni siti indicano che il materiale bianco e' idrossido di potassio (per pile alcaline) ma la reazione (ripresa da qui) produce acqua e non gas per cui non e' quello che ho visto io
NaOH(aq) + CH3COOH(aq) → CH3COONa(aq) + H2O(l)
Insomma, non so perche' ma decisamente funziona
Ho provato lo stesso sistema su una vecchia calcolatrice Casio di fine anni 70. In questo caso l'ossido si presenta di colore verde rame (non so se e' il colore del contatto ossidato od il colore di quanto fuoriuscito dalla batteria). I contatti si presentano fortemente corrosi
In questo caso il sistema dell'aceto non funziona. Credo che in quel periodo si usassero pile con composizione differente
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...