mercoledì 8 giugno 2016

Mandelbrot su C64 in Assembler

Frugando su internet ho trovato la versione in Assembler di Mandelbrot per C64 compresa nel progetto Resurrection (sotto cartella Mandelbrot)

Il codice e' ben commentato ed il risultato e' in modalita' testo



Il tempo di calcolo su VICE in emulazione del tempo reale del C64 risulta essere di 90 secondi con 26 iterazioni per punto
Il codice e' compilabile con il crosscompiler ACME e necessita della libreria stdlib
----------------------------------------------------------------
;Mandelbrot test code

!source "../stdlib/stdlib.a"
!to "Mandelbrot.prg", cbm
!sal
!sl "Mandelbrot.map"
!svl "Mandelbrot.lbl"
!cpu 6510
!ct pet

!source "../stdlib/BASICEntry80d.a"

!macro OutputFAC {
jsr $bddd ; Convert FAC#1 to ASCII String. Kills FAC#2
jsr $b487 ; Set Up String
jsr $ab21 ; Output String
}

LDFAC = $bba2
STFAC = $bbd4
SUBFAC = $b850
DIVFAC = $bb0f
CMPFAC = $bc5b
MULFAC = $ba28
ADDFAC = $b867
SETFAC = $b391

!macro LoadFAC .addr {
lda #<.addr
ldy #>.addr
jsr LDFAC
}

!macro StoreFAC .addr {
ldx #<.addr
ldy #>.addr
jsr STFAC
}

!macro SubMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr SUBFAC
}
!macro SubFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+SubMemFAC Temp
}

!macro DivMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr DIVFAC
}
!macro DivFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+DivMemFAC Temp
}

!macro CmpFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+CmpMemFAC Temp
}
!macro CmpMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr CMPFAC
}

!macro MulMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr MULFAC
}

!macro AddMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr ADDFAC
}

!macro SetFAC_Y {
lda #0
jsr SETFAC
}

kMaxIterations = 26

!zn
*=BASICEntry
cld
jsr CINT


; Speed testing for some FP ops. As we can see even some simple operations are very slow
!if 0 {
sei
.tl1
lda #0
sta VIC2BorderColour
+MACROWaitForRaster 64
inc VIC2BorderColour

+LoadFAC xmin
inc VIC2BorderColour

+SubMemFAC xmax
inc VIC2BorderColour

+DivFACMem ScrW
inc VIC2BorderColour

+StoreFAC xs
inc VIC2BorderColour

+MulMemFAC xs
inc VIC2BorderColour

+StoreFAC xs
inc VIC2BorderColour

jmp .tl1
}

; The main Mandelbrot code.
;xs=(xmax-xmin)/40.0;
+LoadFAC xmin
+SubMemFAC xmax
+DivFACMem ScrW
+StoreFAC xs

;ys=(ymax-ymin)/24.0;
+LoadFAC ymin
+SubMemFAC ymax
+DivFACMem ScrH
+StoreFAC ys

;for (y=0;y<24;y++) {
lda #0
sta y

.l1
;   for (x=0;x<40;x++) {
lda #0
sta x

.l2
;      p=xmin+(x*xs);
ldy x
+SetFAC_Y
+MulMemFAC xs
+AddMemFAC xmin
+StoreFAC p


;      q=ymin+(y*ys);
ldy y
+SetFAC_Y
+MulMemFAC ys
+AddMemFAC ymin
+StoreFAC q


;         xtemp=0;
;         x0=0;
;         y0=0;
ldy #0
+SetFAC_Y
+StoreFAC x0
+StoreFAC y0


;         i=0;
lda #0
sta i

.while
;         while (((x0*x0)+(y0*y0))<4 && ++i<kMaxIterations)  {
; i check, first, simple integer check
lda i
cmp #kMaxIterations
bcc .ltkMaxIterations

jmp .escape
.ltkMaxIterations

; mul check
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+AddMemFAC Temp2
+CmpFACMem Escape
bcc .lt4
jmp .escape
.lt4

;++i
inc i

; xtemp = (x0*x0) - (y0*y0) + p
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+SubMemFAC Temp2
+AddMemFAC p
+StoreFAC xtemp

;            y0=(2 * x0 * y0) +q;
+LoadFAC x0
+MulMemFAC y0
+StoreFAC Temp2
ldy #2
+SetFAC_Y
+MulMemFAC Temp2
+AddMemFAC q
+StoreFAC y0


;            x0=xtemp;
+LoadFAC xtemp
+StoreFAC x0

;            }
jmp .while

.escape
; Range check to adjust for printable characters
lda i
; lsr ; Potential for shit adjustment, change kMaxIterations to accomodate
cmp #26 ; Letters in the alphabet!
bcc .okChar
lda #' '
jmp .rawOut
.okChar
clc
adc #64
.rawOut
jsr CHROUT

; Finish for loops
inc x
lda x
cmp #40
beq .ol2
jmp .l2
.ol2
inc y
lda y
cmp #24 ; MPi: TOOD: Keep the last line clear for an IRQ scrolling message
beq .ol1
jmp .l1
.ol1

.flash
; inc VIC2BorderColour
jmp .flash

; C64 Floating point values
; MPi: TODO: Must update the assembler to create these
xmin !by $82, $a0, $00, $00, $00 ; -2.5
xmax !by $81, $40, $00, $00, $00 ; 1.5
ymin !by $81, $c0, $00, $00, $00 ; -1.5
ymax !by $81, $40, $00, $00, $00 ; 1.5
ScrW !by $86, $20, $00, $00, $00 ; 40
ScrH !by $85, $40, $00, $00, $00 ; 24
Escape !by $83, $00, $00, $00, $00 ; 4

; Float storage
Temp = *
Temp2 = * + 5
xs = * + 10
ys = * + 15
p = * + 20
q = * + 25
xtemp = * + 30
x0 = * + 35
y0 = * + 40
; Bytes
x = * + 45
y = * + 46
i = * + 47
----------------------------------------------------------------



IEEE 754

Si tratta di un metodo di memorizzazione di numeri float  con varia lunghezza nel numero di bit (in questo caso sara' utilizzata solo la rappresentazione a 32 bit). Un convertitore on line di numeri in formato IEEE754 puo' esssere trovato a questo link

I bit sono cosi' divisi
1 bit di segno
8 bit di esponente : 2 elevato all'esponente
23 bit : mantissa del numero

In questo formato i numeri 12.5 e 3.5 ottengono la seguente rappresentazione binaria

12.5  0 10000010 10010000000000000000000  1.5625   4718592
3.5    0 10000000 11000000000000000000000  1.75     6291456

il primo bit e' in entrambi i casi 0 perche' i due numeri sono positivi

12.5 puo' essere espresso come 2^3 *1.5625. L'esponente e' quindi 3 ma deve essere sommato il valore di 127 per cui l'esponente e' 127 + 3 = 130d =  10000010b. Infine 10010000000000000000000 e' la rappresentazione binaria di 1.5625

Lo stesso si puo' ripetere per il numero 3.5 che puo' essere espresso come 2^1*1.75

Per sommare i due numeri si procede allineando gli esponenti a quello piu' basso (in questo caso 1). 12.5 viene quindi espresso come 6.25*2^1 (spostando l'esponente di due si moltiplica la mantissa per quattro ovvero 2^spostamento). A questo punto si sommando le mantissa e la somma e' uguale a (6.25+1.75)*2^1 = 8*2=16 ovvero il risultato desiderato (12.5+3.5)

per moltiplicare i due numeri (12.5*3.5=43.75) si procede sommando gli esponenti e moltiplicando le mantisse. In questo caso 2^(1+3)*(1.5625*1.75)=2.734375*2^4. La mantissa deve essere normalizzata perche' e' superiore a 2 per cui il risultato sara' 1.3671875*2^5 ovvero 43.75


Perche' tanto confusione .. perche' ai computer piacciono i numeri a base due ed interi

Questa e' un sistema standardizzato ma esistono altri modi per descrivere un numero. In questo fantastico documento del 1976 a firma tale Roy Rankin e Steve Wozniak sulle procedure matematiche per il 6502 con una rappresentazione a 32 bit nel formato

 Exponent    Two's Complement Mantissa
  SEEEEEEE  SM.MMMMMM  MMMMMMMM  MMMMMMMM
     n         n+1       n+2       n+3

Repository per Yocto su Intel Edison

Come fatto notare in un precedente post, il repository di default opkg di Intel Edison non e' cosi' fornito cosi' si e' abituati per esempio con Arduino YUN.




La soluzione deriva dalle AlexT's Edison Page,   un repository non ufficiale che riporta un discreto numero di pacchetti di uso comune gia' in formato binario

Per abilitare questo repository si deve aggiungere al file /etc/opkg/base-feeds.conf le seguenti righe

-------------------------------
src/gz all http://repo.opkg.net/edison/repo/all
src/gz edison http://repo.opkg.net/edison/repo/edison
src/gz core2-32 http://repo.opkg.net/edison/repo/core2-32
-------------------------------
si digita quindi
opkg update

(sul sito viene esplicitamente indicato di non usare opkg upgrade ma di configurare l'upgrade pacchetto per pacchetto pena la saturazione della rootfs)
Si possono quindi installare pacchetti come opencv e motion senza fatica

lunedì 6 giugno 2016

Moltiplicazione veloce per 10 in binario

Questo e' un sistema rapido per effettuare moltiplicazioni per 10 su un calcolatore binario ripresa da questo documento

L'idea e' quella di dividere la moltiplicazione per 10 come (numero*8)+(numero*2) che equivale ovviamento a numero numero*(8+2). Il vantaggio di questo procedimento e' che in con codificato binario le moltiplicazione per 2 (e per i suoi multipli) consistono semplicemente in uno spostamento verso sinistra dei bit.

Un esempio: moltiplichiamo 123x10
la codifica binaria di 123 e' 1111011
lo shift di un posto (moltiplicazione per due) e' 11110110
lo shift di tre posti (moltiplicazione per otto) e' 1111011000
la somma binaria di 11110110 + 1111011000 equivale a 10011001110 che corrisponde al risultato desiderato di 1230

Il vantaggio di questo sistema e' che in Assembler esiste un comodo apposito per lo shift binario a sinistra che e' ASL nel 6502 e SHL in x86

mercoledì 1 giugno 2016

Sviluppo assembler su C64

Mi e' presa la voglia di tornare alle origini e programmare in assembler sul MOS 6502 (o meglio sul MOS 6510 del Commodore 64). Ovviamente il computer fisico e' in qualche discarica (o spero recuperato) e cerco di usare l'emulatore VICE

In modo, piu' o meno tradizionale, dopo aver avviato l'emulatore, si deve impiegare un assemblatore (nel caso Turbo Assembler per C64...con una curiosa omonimia con TASM Borland per x86) caricando l'immagine di un disco (preventivamente scaricat) con File/Attach Disk Image/Disk 8
con LOAD"$",8 e successivo LIST si ottiene il contenuto del disco


Si carica l'assemblatore con LOAD"*",8,1 ed al READY si digita SYS36864 entrando nella schermata nera di editing. Questo e' il semplice programma di test che stampa a video una stringa


programma in sintassi TASM
--------------------------------------------------
* = $1000

!basic
    ldx #$00
loop  
    lda message,x
    sta $0400,x
    inx
    cpx #$04
    bne loop
    rts
message .text "luca"
--------------------------------------------------

Per compilare il programma si deve usare la combinazione BackArrow+3 ma BackArrow non esiste sulla tastiera PC; si tratta del tasto piu' in alto a sinistra al di sotto del tasto di ESC (che nella tastiera italiana e' il backslash o barra rovescia)




s per start e si avvia il programma. Per rientrare nella fase di editing e' sufficiente ridigitare SYS 36864


E' comunque piuttosto noioso procedere nel modo classico ed e' molto piu' comodo usare C64 Studio (una IDE con allegato ACME un cross compiler 6502) e che permette di eseguire il programma lanciando autonomamente VICE



La differenza sostanziale tra i due metodi e' che usando C64 Studio si deve scrivere un preambolo in Basic che lancia poi il codice Assembler (in pratica una sola linea di codice BASIC che indichi un SYS49152 per passare il controllo al codice assembler...tale preambolo e' ralizzato con le sole righe *=$0801 ovvero la locazione di memoria dove risiede il compilatore BASIC e !basic.. non risulta necessario impostare *=$01000)

programma in sintassi ACME. Da notare come viene dichiarata la stringa
--------------------------------------------------
;set program start address
* = $0801

!basic
    ldx #$00
loop  
    lda message,x
    sta $0400,x
    inx
    cpx #$04
    bne loop
    rts
message !scr "luca"

fra le altre cose con C64 Studio si puo' utilizzare anche direttamente Basic


ArduinoTheremin

Questo progetto e' stata soltanto una occasione per usare la libreria Mozzi e non puo' considerato completo e finito.
Con Mozzi e' possibile trasformare Arduino in un sintetizzatore usando semplicemente il pin 9 ed il Ground collegandoli ai pin di un jack audio da pcb. Fra le altre cose il segnale in uscita e' cosi' alto che puo' essere direttamente mandato in cuffia senza necessita' di amplificazione


L'idea e' quella di usare due sensori ultrasonici SR-04 per controllare la frequenza ed il volume. Il problema e' che Mozzi usa i timer di Arduino per la propria necessita' di produzione audio e quindi SR-04 non e' il componente piu' adatto per interfacciarsi a Mozzi




le frequenze sono scalate da 4 a 40 cm con frequenze da 100 a 660 Hz (la frequenza e' stata poi portata 4 ottave piu' alto) mentre il volume va da 0 al massimo passando da 4 a 40 cm

la base utilizzata deriva da questo sketch
---------------------------------------------------------
/*
This file uses a Ultrasonic Sensor code that was
 modified from the a code found on: 
 http://winkleink.blogspot.ca/2012/05/arduino-hc-sr04-ultrasonic-distance.html
 and modified codes from Mozzi examples and reference documentation.
 */

// Include Mozzi Classes
#include <MozziGuts.h>;
#include <mozzi_config.h>
#include <Oscil.h>;
#include <tables/sin1024_int8.h>;
#include <tables/saw2048_int8.h>;
#include <tables/cos2048_int8.h>;
#include <mozzi_rand.h>;
#include <LowPassFilter.h>;

#define CONTROL_RATE 64

Oscil <2048, AUDIO_RATE> osc(SAW2048_DATA); // Oscilator waveform
Oscil <COS2048_NUM_CELLS, CONTROL_RATE> filterMod(COS2048_DATA); // Low Pass Filter waveform
Oscil <2048, CONTROL_RATE> kvib(SAW2048_DATA); // Vibrato Waveform
LowPassFilter lpf;

// Ultrasonic Sensor Pins
int trigPin = 11;
int echoPin = 12;
// Ultrasonic Sensor Pins
int trigPin2 = 8;
int echoPin2 = 7;

byte volume;

void setup(){
  Serial.begin(115200);
  startMozzi(CONTROL_RATE);
  //lpf.setResonance(20);
  kvib.setFreq(16.5f);
  filterMod.setFreq(1.3f);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(trigPin2, OUTPUT);
  pinMode(echoPin2, INPUT);
}

void updateControl(){

  // Distance Sensor
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(100);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  int freq = map(distance, 4, 40, 100, 660);
  /*
  C = 261
  C#= 277
  D = 293
  D#= 311
  E = 329 
  F = 349
  F#= 369
  G = 391
  G#= 415
  A = 439
  A#= 466
  B = 493
  C = 523
  */
  
  
  int duration2, distance2;
  digitalWrite(trigPin2, HIGH);
  delayMicroseconds(100);
  digitalWrite(trigPin2, LOW);
  duration2 = pulseIn(echoPin2, HIGH);
  distance2 = (duration2/2) / 29.1;
  volume = map(distance2, 4, 40, 0, 255);
  
  byte cutoff_freq = 100 + filterMod.next()/2;
  lpf.setCutoffFreq(cutoff_freq);
  osc.setFreq(freq*2);

  //float depth = 1; // vibrato depth
  //float vibrato = depth * kvib.next();

  /*if (rand(CONTROL_RATE/2) == 0) // Low Pass Filter Frequency
  {
    filterMod.setFreq((float)rand(255)/64);
  }
  byte cutoff_freq = 100 + filterMod.next()/2;
  lpf.setCutoffFreq(cutoff_freq);

  if(xRead > 500){
    osc.setFreq(freq);
  }
  else if(xRead < 500){
    osc.setFreq(freq*4);
  } */
}

int updateAudio(){
  char audio = (lpf.next(osc.next())*volume)>>8;
  return (int) audio;
}

void loop(){
  audioHook(); 
}

lunedì 30 maggio 2016

Foto aeree con Google Carboard

Visto che l'esperimento con gli anaglifi era riuscito ma non nel modo ottimale ho provato a migliorare, questa volta usando un vero stereoscopio,ovvero Google Cardboard, anche se dal costo decisamente economico (uno stereoscopio da tavolo per foto aeree costa sopra il migliaio di euro)


Sul telefono ho montato una semplice pagina web sul telefono Android che scalava e centrava i due fotogrammi precedentemente registrati a mano (in versioni successive sarebbe comodo avere la possibilita' di spostare uno dei fotogrammi via telecomando bluetooh per centrare le immagini guardando nel visore)

Con questo sistema la visualizzazione 3D e' decisamente buona e molto piu' simile a quella del vero stereovisore per foto aeree rispetto a quella anaglifica

index.html
-------------------------
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class ="stereo">
    <div id="sinistra">
      <img alt="Sinistra" title="Sinitra" src="594_2.png" style="width: 100%; max-height: 100%"/>
   </div>
    <div id="destra">
      <img alt="Sinistra" title="Sinitra" src="595_2.png" style="width: 100%; max-height: 100%"/>

   </div>
</div>
</body>
-------------------------

style.css
-------------------------
.stereo{
        width: 100%;
        overflow: hidden;
    }

    #sinistra {
        float: left;
        width: 50%;
    }
   #sinistra img
   {

      margin: auto;
      display: block;
   }
    #destra {
        float: left;
        width: 50%;
    }
   #destra img
   {
      margin: auto;
      display: block;
   }
-------------------------



Foto aeree con anaglifi

A lavoro mi capita spesso la necessita' di visualizzare foto aeree ma non ho un visore stereoscopico. Ho scoperto un sistema semplice (e lecito) per scaricare le stereocoppie dal sito della Regione Toscana (evitando un generoso esborso) e cosi' mi sono messo alla ricerca di un sistema per visualizzare la terza dimensione


Il primo tentativo e' stato quello di utilizzare gli anaglifi mediante l'uso degli occhialini rossi/ciano (qualcuno si ricorda del film lo Squalo 3D??)

Il sistema piu' semplice, una volta scelti i due fotogrammi, e' quello di usare il programma AnaBuilder che permette di coregistrare in automatico le due immagini sia come traslazione che come rotazione dal menu Actions/AutoFit with borders detection


Il risultato non e' male, anche considerando che non c'e' intervento umano, ma il programma riesce a lavorare solo su piccole porzioni della stampa. Introducendo una stampa completa della foto aerea, normalmente in formato 24x24 cm scannerizzata poi a 600 dpi, il programma si blocca.



Il risultato finale e' una immagine blandamente in 3D perche' manda tutta l'esagerazione verticale che fornisce un vero stereoscopio

ps. per scaricare la stereocoppie si puo' andare su Geoscopio, selezionare l'area di interesse, cliccare su Fotogrammi per esempio 2013 (non tutti gli anni hanno la copertura completa del territorio!!) , poi con lo strumento Freccia +, si seleziona uno squadro di un fotogramma e si clicca su visualizza fotogramma. Si ripete il tutto con il fotogramma vicino ed abbiamo una stereocoppia giocando con  poi con i livelli di zoom per avere il dettaglio desiderato. Per rimuovere la finestra della legenda si puo' premere il tasto h (il visualizzatore di immagini e' IIPImage)


Fauna caldinese - Nido

Nido, forse di passero, caduto a terra








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

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



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

In questa modalita' vengono mostrate le query per secondo e le query lente con il traffico di rete











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.

Schermata di amministrazione

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.







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

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

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

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

lunedì 16 maggio 2016

Opzioni di compilazione gcc in Eclipse e Netbeans

Un promemoria su come configurare gli switch di compilazione di gcc con Eclipse e Netbeans
In entrambi i casi si deve cliccare destro sul nome del progetto ed aprire le proprieta'

Eclipse

Optimizzazione e debug -O3 -Wall

 Include switch -I
Per lo switch -lm per esempio si scrive sono m omettendo -l
Library switch -l -L


Netbeans

Inclusione di librerie ed headers


Per aggiungere lo switch -l in Netbeans si apre Add Option/Other Option e si digita lo switch completo (al contrario di Eclipse)


collect2.exe: ld returned error 5 exit status

L'errore ld returned error 5 sul file collect2.exe  dovrebbe essere limitato all'IDE di Arduino 1.6.8 su piattaforma Windows XP.

In pratica compilando sketch perfettamente funzionanti puo' verificarsi che non venga generato l'eseguibile


L'errore e' visibile solo abilitando l'output dettagliato in fase di compilazione (da File/Impostazioni/Mostra output dettagliato) e si tratta dell'impossibilita' di rinominare un file temporaneo


L'errore non e' presente nella versione per Linux od in versioni precedenti dell'IDE di Arduino







LLama3 Anita

A seguito di questo post ho provato a vedere ho provato a vedere cosa accadeva ad utilizzare un modello specifico per la lingua italiana in...