martedì 15 maggio 2012

Arduino Bluetooth v 06

Connessione di alimentazione della Arduino BT ... di fatto non ha una connessione USB quindi ha solo alimentazione esterna che deve essere inferiore a 5.5 Volts ed assolutamente della giusta polarita' pena la compromissione dell'elettronica .

Il codice per fare l'accoppiamento e' 12345
La versione 06 monta il processore ATMEGA 168 (importante da settare nel software di programmazione)


Programmare la scheda Bluetooth e' un po' piu' difficile rispetto alla versione USB
la procedura prevede

hcitool scan per verificare l'address della scheda

dopo di cio' si crea la porta seriale virtuale per la programmazione

sudo rfcomm bind rfcomm0 00:07:80:90:51:17 1

dando il comando rfcomm si puo' verificare la connessione avvenuta

in seguito si deve andare nella directory /lib/ ed editare il file preferences.txt

modificando alla fine del file


serial.port=/dev/rfcomm0
serial.databits=8
serial.stopbits=1
serial.parity=N
serial.debug._rate=115200
serial.burn_rate=115200
board=bt

(per usare piu' schede uso due installazione del software, una per la versione USB ed una per la BT)

ed infine la parte difficile
una volta compilato lo sketch per fare l'upload sulla scheda si deve premere il tasto RESET sulla scheda BT (e' l'unico pulsante presente) e subito dopo premere il pulsante di upload sul software Arduino. La giusta scelta di tempo e' fondamentale per l'upload

Il tasto di upload e' il secondo da destra nella barra in alto


Puo' essere comodo montare un LED sul pin digitale 13 perche' da qui si puo' vedere quando viene fatto il reboot






Accelerometro LIS3LV02DQ su Arduino

La prova reale dell'accelerometro LIS3LVV02DQ collegato come I2C ad una Arduino
Le resistenze di Pull-Off sono da 1.5 KOhm


Lo sketch caricato e' il seguente (ripreso da qui)
-----------------
#include <Wire.h>


// TWI (I2C) sketch to communicate with the LIS3LV02DQ accelerometer


//Modified code from http://research.techkwondo.com/blog/julian/279
//Thanks Julian.
 
void setup()

{

  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);

  Serial.println("Wire.begin");
  Wire.beginTransmission(0x1D);  Wire.send(0x20); // CTRL_REG1 (20h)
  Wire.send(0x87); // Device on, 40hz, normal mode, all axis's enabled
  Wire.endTransmission();
}

void loop()
{
#define i2cID 0x1D#define outXhigh 0x29
#define outYhigh 0x2B
#define outZhigh 0x2D
#define outXlow 0x28
#define outYlow 0x2A
#define outZlow 0x2C
byte z_val_l, z_val_h, y_val_l, y_val_h, x_val_l, x_val_h; 
//----------X Values-----------------------
  int x_val;
//-------------------------------   Wire.beginTransmission(i2cID);
  Wire.send(outXlow);
  Wire.endTransmission(); 
Wire.requestFrom(i2cID, 1); while(Wire.available())
 {
   x_val_l = Wire.receive();
 }
 //------------------------------- 
  Wire.beginTransmission(i2cID);
  Wire.send(outXhigh);
  Wire.endTransmission();
Wire.requestFrom(i2cID, 1);if(Wire.available())
 {
   x_val_h = Wire.receive();
 }
//------------------------------- 
 x_val = x_val_h; x_val <<= 8;
 x_val += x_val_l;




//----------Y Values-----------------------
  int y_val;
//-------------------------------   Wire.beginTransmission(i2cID);
  Wire.send(outYlow);
  Wire.endTransmission(); 
Wire.requestFrom(i2cID, 1); while(Wire.available())
 {
   y_val_l = Wire.receive();
 }
 //------------------------------- 
  Wire.beginTransmission(i2cID);
  Wire.send(outYhigh);
  Wire.endTransmission();
   
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   y_val_h = Wire.receive();
 }
//------------------------------- 
 y_val = y_val_h; y_val <<= 8;
 y_val += y_val_l;




 //----------Z Values-----------------------
  int z_val;
//-------------------------------   Wire.beginTransmission(i2cID);
  Wire.send(outZlow);
  Wire.endTransmission(); 
Wire.requestFrom(i2cID, 1); while(Wire.available())
 {
   z_val_l = Wire.receive();
 }
 //------------------------------- 
  Wire.beginTransmission(i2cID);
  Wire.send(outZhigh);
  Wire.endTransmission();
   
Wire.requestFrom(i2cID, 1);
if(Wire.available())
 {
   z_val_h = Wire.receive();
 }
//------------------------------- 
 z_val = z_val_h; z_val <<= 8;
 z_val += z_val_l;

Serial.print("x_val= "); Serial.println(x_val, DEC);

Serial.print("y_val= "); Serial.println(y_val, DEC);
Serial.print("z_val= "); Serial.println(z_val, DEC);

delay(250);
}
-----------------

I risultati a video (ogni tanto sollevo e faccio ricadere la board sul tavolo per vedere l'effetto)





lunedì 14 maggio 2012

Connessione I2C su Arduino

Il protocollo I2C e' un sistema seriale a 2 cavi con i quali e' possibile interagire con una serie di sensori
Immagine ripresa da qui anche se la mia attrezzatura e' sostanzialmente identica

Le resistenze devono essere da almeno 1K ohm (alcuni usano da 1.5-2 K Ohm mentre altri esempi riportano anche 10 K Ohm)

Il Pin 4 analogico dell'Arduino deve essere collegato a SDA (dati) del sensore
Il Pin 5 analogico dell'Arduino deve essere collegato a SCL (clock) del sensore

GND del sensore deve essere collegato ovviamente al  GND di Arduino cosi' come VDD al 5 Volts di Arduino

E' possibile usare il BUS I2C per mettere insieme piu' sensori, l'importante e' che ogni sensore abbia il proprio ID univoco

Ripreso da qui



Arduino Software su Ubuntu 12.04

Per reiniziare a lavorare su Arduino mi e' stato necessario reinstallare l'ambiente di sviluppo sulla Linux Box Ubuntu 12.04 con qualche grattacapo



Il primo aspetto mancante nell'installazione di Ubuntu e' l'assenza di Java
Successivamente si devono installare le estensioni del compilatore GCC per Avr (il processore dell'Arduino) con i comandi

apt-get install gcc-avr avr-libc binutils-avr

a questo punto si deve scaricare dal sito di Arduino il software per la programmazione che e' presente in due filoni

il filone 1.0 rappresenta il futuro ma non riesce a compilare i vecchi programmi. Nel repository Universe di Ubuntu e' presente un pacchetto arduino che contiene la versione 1.0

la serie 0.xx (attualmente alla versione 0.23) funziona con tutti i vecchi programmi ma non riesce compilare correttamente il primo esempio (Blink) per un errore nel file math.h.

La soluzione (ripresa da qui) consiste nel modificare il file arduino/hardware/arduino/cores/arduino/wiring.h commentando la riga 79 (#define round(x))




martedì 8 maggio 2012

Controllare joypad da Python

Sto cerando di modificare il mio joypad (un Tust GM-1300) per pilotare un piccolo ROV telecomandato con scheda Arduino. Per fare cio' avevo la necessita' di leggere i dati dal joypad e convertirli su una seriale.
Il modo piu' semplice si e' rivelato essere usare Python/Pygame che rileva in modo assolutamente trasparente il joypad USB


Attenzione: per il seguente programma e' necessario che sia presente nella stessa directory dello script Python anche il file pycurse.py che si scarica da questo indirizzo
--------------------------------------------------------------------------------------------
import pygame
import pygcurse

pygame.init()
win = pygcurse.PygcurseWindow(40, 25, 'Rov Controller')

j = pygame.joystick.Joystick(0)
j.init()

try:
    while True:
        pygame.event.pump()
        win.write("Tot.assi : "+str(j.get_numaxes()), x=2, y=1)
        win.write("Tot.pulsanti : "+str(j.get_numbuttons()), x=2, y=2)
        win.write("Asse 1 : "+str(j.get_axis(0)), x=2, y=3)
        win.write("Asse 2 : "+str(j.get_axis(1)), x=2, y=4)
        win.write("Asse 3 : "+str(j.get_axis(2)), x=2, y=5)
        win.write("Asse 4 : "+str(j.get_axis(3)), x=2, y=6)
       
        win.write("Pulsante 1 : "+str(j.get_button(0)), x=2, y=7)
        win.write("Pulsante 2 : "+str(j.get_button(1)), x=2, y=8)
        win.write("Pulsante 3 : "+str(j.get_button(2)), x=2, y=9)
        win.write("Pulsante 4 : "+str(j.get_button(3)), x=2, y=10)
        win.write("Pulsante 5 : "+str(j.get_button(4)), x=2, y=11)
        win.write("Pulsante 6 : "+str(j.get_button(5)), x=2, y=12)
        win.write("Pulsante 7 : "+str(j.get_button(6)), x=2, y=13)
  

except KeyboardInterrupt:
    j.quit()




martedì 17 aprile 2012

AsyncTask e Pi Greco

Partendo da un esempio ripreso da qui e' stato possibile sviluppare un programma che evita il problema del post precedente, ovvero viene sviluppato un calcolo molto lungo senza che Android generi un errore.
Il sistema si basa sull'utilizzo dei task asincroni.

Il programma che calcola il valore di Pi Greco mediante il metodo di Montecarlo
Il task asincrono viene lanciato dall'evento EventTouch..per evitare che pressioni multiple possano generare piu' task asincroni viene settata la variaible booleana corre quando il primo task asincrono parte e non viene rilasciata fino al suo termine
-------------------------------------------------------------------------------
package com.async;

import java.util.Random;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;

public class AsyncActivity extends Activity {
  //queste variabili sono visibili sia dal Main che dal TaskAsync

boolean corre;
double q = 0;
private TextView pi;

//*********** Task Asincrono per il calcolo
public class BackgroundAsyncTask extends  AsyncTask<Void, Boolean, Void> {
 

private ProgressDialog pDialog;

@Override
 protected Void doInBackground(Void... params) {


     //calcolo di PiGreco
     double s = 0;
     int max_cicli = 10000;
     Random generator = new Random();
   
     for (int t=0;t<max_cicli;t++)
     {
         Log.d("task",Double.toString(t));
         double x = (2*generator.nextDouble())-1;
         double y = (2*generator.nextDouble())-1;
         double a = (x*x)+(y*y);
         if (a<=1)
             {
             s++;
             }
     }
     q = (4*s/max_cicli);
 return null;
 }

 @Override
 protected void onPostExecute(Void result) {

//evento generato al termine del task
  corre = false;
  pDialog.dismiss();
  pi.setText(Double.toString(q));
 }

 @Override
 protected void onPreExecute() {

//evento generato all'inizio del task
  corre = true;
  pDialog = ProgressDialog.show(AsyncActivity.this,"Prego attendere...", "Calcolo in corso ...", true);
 }

 @Override
 protected void onProgressUpdate(Boolean... values) {

 }
}

//******** MAIN
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      pi = (TextView) findViewById(R.id.pigreco);
  }

  public boolean onTouchEvent(MotionEvent event)
  {
  if (!corre) new BackgroundAsyncTask().execute();
  return false;
  }
}

lunedì 16 aprile 2012

ANR su Android

tentando di modificare il codice di Mandelbrot per aggiungere uno zoom basato sull'evento touch mi sono imbattuto nel seguente errore
Reacting to signal 3 Wrote stack traces to '/data/anr/traces.txt'

indagando un po' meglio ho capito di essermi imbattuto in un errore di ANR (Application Not Responding) che viene segnalato quando l'applicazione non risponde ad un evento di input entro 5 secondi (questo il mio caso) oppure un task non e' finito entro 10 secondi

Fino a quando l'insieme di Mandelbrot viene gestito nella procedura principale la procedura termina correttamente mentre quando il comando calcola() viene lanciato dall'evento TouchEvent il programma si blocca.






di seguito il codice per riprodurre l'errore


package com.mandelbrot.explorer;


import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.widget.ImageView;

public class MandelbrotExplorerActivity extends Activity {
    private static double re_min = -2.5;
    private static double re_max = 1.0;
    private static double im_min = -1.0;
    private static double im_max = 1.0;
    private static int iterazioni = 100;
    private double y;
    private double x;
    private double ynew;
    private double xnew;
    private int test;
    private double re_factor;
    private double im_factor;
    public boolean zoom;
    public Bitmap bitmap;
    public Paint paint;
    public Canvas canvas;
    private int width;
    private int height;
    private double b;
    private double a;
    public ImageView view;
   
    /** Called when the activity is first created. */
    private void calcola(double re_min1, double re_max1, double im_min1, double im_max1)
    {
        zoom = false;
          
        re_factor = (re_max1 - re_min1);
        im_factor = (im_max1 - im_min1);
  
        // recupera le informazioni sulle dimensioni dello schermo

        for (int i=0;i<width;i++)
        {
            for (int j=0;j<height;j++)
            {
                b = im_min + i * im_factor / width;
                a = re_min + j * re_factor / height;
                x = 0.0;
                y = 0.0;
                test = 0;
                for (int k=0;k<iterazioni;k++)
                {
                      xnew = x * x - y * y + a;
                      ynew = 2 * x * y + b;
                      if (((xnew*xnew)+(ynew*ynew))>4)
                      {
                          test = k;
                          k = iterazioni;
                         
                      }
                      x = xnew;
                      y = ynew;
                }
           
                if (test%2 == 1)
                {
                    //punto bianco
                    canvas.drawPoint(i, j, paint);

                }
            }
           
        }
        zoom = true;
    }
   
    public void onCreate(Bundle savedInstanceState) {
        //StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().penaltyDeath().build());

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        view = (ImageView) findViewById(R.id.imageView1);

        Display display = getWindowManager().getDefaultDisplay();
        width = display.getWidth(); //240
        height = display.getHeight();//320
        
        bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
        
        paint = new Paint();
        paint.setColor(Color.WHITE);
        canvas = new Canvas(bitmap);
        
        canvas.drawColor(Color.BLACK);
       
        view.setImageBitmap(bitmap);
  
        calcola(re_min,re_max,im_min,im_max);
    }

    public boolean onTouchEvent(MotionEvent event) {
        int x = (int)event.getX();
        int y = (int)event.getY();
        Log.d("pos_x",Double.toString(x));
        Log.d("pos_y",Double.toString(y));
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
        }
       
        calcola(-1.0,0.5,-1.0,0.5);
    return false;
    }

}



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