mercoledì 30 novembre 2011

PIC12F683 - Led blinking


Durante la costruzione di un circuito in grado di generare toni DTMF, per testare il corretto funzionamento del clock esterno a 20mhz ho impostato il firmware per fare lampeggiare il led (1sec on, 1 sec. off).
Di seguito il dettaglio del firmware caricato:

@ __config _HS_OSC & _WDT_ON & _MCLRE_ON & _CP_OFF
DEFINE OSC 20
Led VAR GPIO.1
mainloop:
    high LED 
    pause 1000
    low led
    pause 1000
Goto mainloop 

End

Per utilizzare il quarzo esterno oda 20mhz occorre comunicarlo al compilatore (DEFINE OSC 20); successivamente è necessario modificare il file 12F683.INC nella cartella PBP commentando la riga seguente (con il carattere ;)
__config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _CP_OFF

altrimenti in fase di linking viene segnalatol'errore "Overwriting previous address contents (2007)".

I componenti utilizzati sono:
PIC12F683
CONDENSATORE 10nF
QUARZO 20MHZ
2 CONDENSATORI DA 22pf
LED BLU

lunedì 28 novembre 2011

Android tips #2 - Make an 'option menù'



Se volete aggiungere un option menù alla vostra applicazione fate come segue:



1) Creazione del file 'menu.xml' seguente nella cartella 'res/menu' :
 




<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item android:id="@+id/m_info" android:icon="@drawable/info" android:title="@string/info" /> 

<item android:id="@+id/m_clear" android:icon="@drawable/clear" android:title="@string/clear" />

<item android:id="@+id/m_close" android:icon="@drawable/close" android:title="@string/close" /> 

</menu>

Nel file ho assegnato gli identificativi m_email, m_help, m_clear e m_close; utilizzo le icone (res/drawable) email.png, hlp.png, clear.png e close.png e visualizzo/utilizzo nel menù le stringe definite nel file (res/values) strings.xml.
Una guida ai formati delle icone è consultabile al seguente link: http://developer.android.com/guide/practices/ui_guidelines/icon_design_menu.html
Nella mia activity occorre poi definire il metodo (override) seguente per caricare il menù com definito nel file precedente.

@Override
public boolean onCreateOptionsMenu(Menu menu) 
{
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.menu, menu);
   return true;
}
Una volta scelta la voce di menù; nell'applicazione occorre definire (override) il metodo seguente:
@Override
public boolean onOptionsItemSelected(MenuItem item) 
{
switch (item.getItemId()) 
{
   case R.id.m_clear:
   //azione clear 
   return true;
   case R.id.m_close:
   //azione close
   return true;

   default:
   return super.onOptionsItemSelected(item);
}
}
 
That's all folk!

lunedì 21 novembre 2011

Android tips #1 - Make Google Navigator Intent


Se il vostro obiettivo è eseguire l'applicazione Google Navigator verso una destinazione precedentemente acquisita e memorizzata nelle SharedPreferences è sufficente incollare il codice seguente nella vostra applicazione:

1) Creare un oggetto LocationListener per agganciare la posizione:





private static final String C_PREFS_NAME = "gnav";

private static final int C_TWO_MINUTES = 1000 * 60 * 2;

private static final String C_LATITUDE = "latitude";
private static final String C_LONGITUDE = "longitude";

LocationListener mLocationListener = new LocationListener()
{   
public void onLocationChanged(Location location) {
if (isBetterLocation(location, currentBestLocation))
{
currentBestLocation = location;
SharedPreferences settings = getSharedPreferences(
C_PREFS_NAME, 0);  
SharedPreferences.Editor editor = settings.edit();     
editor.putString(
C_LATITUDE, Double.toString(currentBestLocation.getLatitude()));
editor.putString(
C_LONGITUDE, Double.toString(currentBestLocation.getLongitude()));
editor.commit();
}
}

protected boolean isBetterLocation(Location location, Location currentBestLocation)
{
if (currentBestLocation == null) {
return true;
}

  // Check whether the new location fix is newer or older
  long timeDelta = location.getTime() - currentBestLocation.getTime();
  boolean isSignificantlyNewer = timeDelta > C_TWO_MINUTES;
  boolean isSignificantlyOlder = timeDelta < -C_TWO_MINUTES;
  boolean isNewer = timeDelta > 0;
  // If it's been more than two minutes since the current location, use
  // the new location
  // because the user has likely moved
  if (isSignificantlyNewer) {
   return true;
   // If the new location is more than two minutes older, it must be
   // worse
  } else if (isSignificantlyOlder) {
   return false;
  }
  // Check whether the new location fix is more or less accurate
  int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
    .getAccuracy());
  boolean isLessAccurate = accuracyDelta > 0;
  boolean isMoreAccurate = accuracyDelta < 0;
  boolean isSignificantlyLessAccurate = accuracyDelta > 200;
  // Check if the old and new location are from the same provider
  boolean isFromSameProvider = isSameProvider(location.getProvider(),
    currentBestLocation.getProvider());
  // Determine location quality using a combination of timeliness and
  // accuracy
  if (isMoreAccurate) {
   return true;
  } else if (isNewer && !isLessAccurate) {
   return true;
  } else if (isNewer && !isSignificantlyLessAccurate
    && isFromSameProvider) {
   return true;
  }
  return false;
 }
 /** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null)
{
return provider2 == null;
}
return provider1.equals(provider2);
}

2) Recuperare la posizione precedentemente memorizzata e aprire Google Navigator.
...
SharedPreferences settings = getSharedPreferences(C_PREFS_NAME, 0);        
String uri = "google.navigation:q=" + settings.getString(C_LATITUDE,"") + "," + settings.getString(C_LONGITUDE, "");
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(intent);

...

domenica 20 novembre 2011

PIC18F4550 - Pinguino Bot controlled by PC



Una prima versione del bot era controllata da un programma scritto in visual basic sempre tramite un adattatore bluetooth in modalità COM port. Una volta accoppiato l'adattatore bluetooth ad una porta COM  occorre ovviamente aprire la porta seriale:

Private Sub CmdImposta_Click()
    On Error Resume Next

    If MSComm1.PortOpen Then
        MSComm1.PortOpen = False
    End If
   
    MSComm1.CommPort = CInt(Mid(ComboPort.Text, 4))
    MSComm1.Settings = "115200,N,8,1"
    MSComm1.RThreshold = 1
    MSComm1.DTREnable = False
    MSComm1.InputLen = 1
    TxtImpostazioni.Text = MSComm1.Settings
    MSComm1.PortOpen = True
    If Err.Number > 0 Then
        Err.Clear
        TxtStato.Text = "Errore COM" & MSComm1.CommPort
        Exit Sub
    End If
    TxtStato.Text = "Porta COM" & MSComm1.CommPort & " aperta"
End Sub


Il collegamento è effettuato a 115.200baud; vengono trasmessi al pc i dati della tensione delle batterie, la lettura sonar di eventuali ostacoli e la posizione della testa servo.
Per fare avanzare il bot occorre inviare il carattere 'W' al firmware:

Private Sub CmdAvanti_Click()
    MSComm1.Output = "W"
    TxtStato.Text = "Send 'W' char"
End Sub


La tensione della batteria 7.2V viene rilevata, tramite partitore di tensione con due resistenze da 10K, all'ingresso ADC del pinguino. La lettura della batteria (ADC a 10bit) va prima trasformata nella scala corretta:
...
volt = FormatNumber((value * 5 * 2) / 1023, 3)
progValue = (100 * volt) / 7.2
...
Il valore di progValue viene poi inviato alla progressBar per la visualizzazione.

La durata dell'impulso del sonar va trasformato per ricavare la distanza dell'ostacolo in cm:
...
Private Function GetSonarCM(ByVal value As String) As Double
    Dim sonar_out_cm As Double
    Const SONAR_SENS As Double = 147 / 2.54   '373.38  'us/cm
    Const TOSC As Double = 0.667 'us
    sonar_out_cm = value * TOSC / SONAR_SENS
    GetSonarCM = FormatNumber(sonar_out_cm, 2)
End Function

...

Con la posizione del servo (servo.getPosition()) inviata al programma visual basic e la distanza dell'ostacolo in cm è ora possibile disegnare il punto rilevato nello schema radar. La funzione servo.getPosition() restituisce un valore da 0 a 255 corrispondente a 0 gradi fino all'apertura massima consentita dal servo.

mercoledì 16 novembre 2011

Quick Response


Ultimamente vedo 'qr code' ovunque; nelle T-shirt, al supermercato, sui giornali...
Perchè essere da meno! Siete curiosi ? Puntate lo smartphone e ...

martedì 15 novembre 2011

Linguine all'astice


Dimenticavo di dire che un altra passione è il cibo e visto l'orario condivido con Voi queste linguine all'astice. Che profumo...

lunedì 14 novembre 2011

PIC12F683 - PWM motor/light dimmer


Oggi presentiamo un regolatore o dimmer per motori / lampade in bassa tensione (12V o 24V). Cuore del circuito è il PIC12F683 equipaggiato di un modulo CPP e un convertitore ADC 8/10 bit. Di seguito il collegamento al datasheet:
http://ww1.microchip.com/downloads/en/devicedoc/41211d_.pdf
Mediante il partitore di tensione formato dal potenziometro lineare da 5K portiamo in ingresso del convertitore ADC (PIN 3) una tensione variabile da 0 a 5V. Il valore letto a 8 bit viene passato come 'duty cycle' al modulo CPP per la generazione dell'onda quadra sul pin di uscita (PIN 5).




Di seguito parte del codice in linguaggio PBP.


Define ADC_BITS 8               ' Set number of bits in result
Define ADC_CLOCK 3          ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS
ANSEL = 111000             ' Set AN3 analog, rest digital
CMCON0 = 7                           ' Analog comparators off
...
mainloop:
    ADCIN 3, adval
    hPWM 1, adval, 30000
Goto mainloop



PIC18F4550 - Pinguino bot controlled by Android



Il robot è autocostruito con lastre in plastica semirigida tagliata con un cutter. Le parti ad angolo sono state tagliate parzialmente, creata la piega e quindi fermata con della colla a caldo. I due servo e il sensore a ultrasuoni sono stati acquistati su RobotItaly ai link seguenti: 
http://www.robot-italy.com/product_info.php?cPath=85_28&products_id=1826
http://www.robot-italy.com/product_info.php?cPath=15_48_142&products_id=957 
Altrimenti se si vuole modificare un servo per la rotazione continua seguite la guida al link seguente:
http://www.robot-italy.com/article_info.php?articles_id=1

Per quanto riguarda pinguino (arduino clone) fare riferimento al sito web: http://www.hackinglab.org/
Di seguito riporto ugualmente il circuito realizzato su scheda millefori. Il quarzo da 20MHz e i condensatori da 22pF sono stati sistemati e saldati sotto il PIC 18F4550 nello zoccolo.



Il modulo bluetooth SPP è stato acquistato su ebay; se ne trovano per tutte le  tasche. Se non volete incappare nella modifica della configurazione mediante comandi AT; prediligere quelli già impostati a 9600 baud.

Il collegamento va fatto tramite la porta UART della scheda pinguino collegando il pin RX con TX e viceversa.




Il modem, infatti, ha i seguenti pin:
- CTS-I da collegare insieme al pin RTS-I
- VCC
- GND 
- TX-0 da collegare con porta rx della UART
- RX-I da collegare con porta tx della UART
- RTS-0 da collegare insieme al pin CTS-I





I segnali RTS (REQUEST TO SEND) - CTS (CLEAR TO SEND) generalmente vengono usati per forzare l'abilitazione del segnale di portante sul doppino telefonico. In pratica il PC deve alzare il segnale RTS ed attendere che il modem risponda alzano il segnale CTS del PC.
Generalmente nelle connessioni tra dispositivi questi segnali vengono simulati creando un ponticello, a livello del connettore del cavo seriale tra i pin dei segnali RTS-CTS, di modo che quando il dispositivo alza il segnale RTS si ritrova automaticamente il CTS attivo.
Utilizzando l'ambiente di sviluppo da hackinglab.org, consultando le varie guide e utilizzando la libreria servo ho caricato sulla scheda pinguino il programma seguente:
void setup(void)
{

 Serial.begin(9600);
 servo.attach(5); //sonar position servo
 servo.attach(6); //right wheel servo
 servo.attach(7); //left wheel servo
}


void loop(void)
{
 if (Serial.available() > 0)
 {
  incChar = Serial.read();

  if (incChar == 'W') {
   //go forward
   servo.setMinimumPulse(6);
   servo.setMaximumPulse(7);
  }

...
... left, right, reverse
...
}



Particolare del sonar montato su un servo. Tramite modulo CCP del PIC18F4550 (Pinguino) viene misurata la durata dell'impulso di uscita del modulo sonar. Di seguito parte del codice del PIC che gestisce la misurazione dell'impulso come differenza fra istante del fronte di discesa e salita.

void UserInterrupt()
{
if(PIR2bits.CCP2IF == 1)  
{               
if(edge1 == 0)              // rising edge
{
rise = (CCPR2H<<8)+ CCPR2L;
CCP2CON = 0x04;      // 00000100; CCP2 as capture mode, now changed to capture on every falling edge
edge1 = 1;           // for falling edge
}
else
{
fall = (CCPR2H<<8)+ CCPR2L;
dur = fall - rise;
TMR3H = 0x0;       // preset for timer3 MSB register
TMR3L = 0x0;       // preset for timer3 LSB register
CCP2CON = 0x05;    //CCP2 now reconfigured to capture mode on very rising edge
edge1 = 0;         // back to rising edge
}
PIR2bits.CCP2IF =  0;
}
}

...

Nella funzione setup di pinguino occorre abilitare il modulo CCP e relativo TIMER 3:

...
TMR3H = 0x0;        // preset for timer3 MSB register
TMR3L = 0x0;        // preset for timer3 LSB register
T3CON = 0b00111101; //Enable timer3 CCP2 clock 8bit read write operation

CCP2CON = 0x05;
PIR2bits.CCP2IF =  0;
PIE2bits.CCP2IE =  1; //Enable interrupt

...

domenica 13 novembre 2011

Hello world!



Buongiorno mondo!
Come appassionato di elettronica, informatica e tutto ciò che ruota attorno è giunto il momento di condividere! Nessuna novità all'orizzonte; prima di cercare altrove passa da 'The electronics hobbyist'; troverai quello che cerchi!

class myfirstjavaprog
{  
        public static void main(String args[])
        {
           System.out.println("hello, world!");
        }
}