jan 242010

Mon premier projet 2010, tout simple mais bien utile: un chargeur de téléphone autonome. Le montage est basé sur une batterie Lithium polymère d’un élément (3.7v) qui alimente un « Mintyboost » transformant le 3.7v en 5V pour charger un périphérique USB. La charge de la batterie est assurée par un courant entre 3 et 6v au travers d’un MAX1555. Ce courant peut provenir de 3 sources:

  • Un port USB d’ordinateur.
  • Un chargeur secteur 5v.
  • Un panneau solaire.

Le montage se base sur 2 cartes open hardware provenant de 2 fournisseurs bien connus sparkfun et Adafruit industries.

L’une des cartes sert de support au MAX1555. Elle comporte 2 entrées et 2 sorties.

En entrée:

  • Un port d’alimentation 2.1mm.
  • Un mini usb.

En sortie:

  • La batterie Lipo.
  • la sortie 3.7v vers le mintyboost.

Elle est disponible préassemblée chez sparkfun

La batterie provient aussi de chez Sparkfun. C’est une batterie 1 élément de 2000 mAh.

L’autre partie, est un kit de chez Adafruit. Le mintyboost. Il n’a qu’un but: élever la tension de la batterie de 3.7v à 5v. Le kit est très simple, il faut moins de 15 min pour l’assembler.

Les instructions d’assemblage, les schémas et tout la documentation sont en ligne sur le site de ladyada.

Le panneau solaire provient lui aussi de chez adafruit.

Dernière étape: assembler l’ensemble dans un boitier de petite taille. J’ai choisi un boitier robuste en aluminium qui n’aura aucun mal à trainer dans un sac à dos.

Inside the box

L’intérieur du boitier. Comme vous pouvez le constater, on peut encore réduire un peu l’encombrement.

It work's !

Mon téléphone en charge. Le chargeur peut assurer à peu près une charge et demi du téléphone sans l’aide du panneau solaire. Avec le panneau il faut une dizaine d’heures pour recharger complètement la batterie du chargeur. Le chargeur est suffisamment petit pour rester dans un sac à portée de main. Quand vous partez en randonnée, il suffit juste d’emporter en plus le panneau solaire que l’on fixera sur le dessus du sac à dos par exemple.

L’avantage c’est qu’il peut être utilisé avec ou sans la partie solaire. Celle-ci assure une totale autonomie: rechargement de la batterie « tampon » dans la journée et charge des périphériques USB la nuit par exemple.

En se qui concerne la facture, elle est relativement élevée: ~90$ Ce chiffre pourrait être fortement réduit  en faisant nous même le circuit. Comme il s’agit d’un prototype, j’ai préféré rester sur le kit, plus simple à assembler.

fév 112009

Comme promis, voici le schéma de la carte principale du montage Arduino PhotoLab

Je débute avec Eagle alors mon schéma n’est pas forcément très clair, mais bon…

photolab

Le voici au format Eagle

  • Prise SENSORS: branchement des capteurs
  • Prise TTL: Branchement d’un convertisseur USB/TTL pour reprogrammer l’arduino.
  • Prise STROBE: Sortie pour la prise de commande du flash ou de l’appareil photo suivant l’usage.
  • Prise POWER: Alimentation 5V par transfo ou pack de piles.

Les 4 boutons permettent de se ballader dans les menus pour choisir les capteurs et changer les valeurs.

Il reste quelques ports dispo sur l’arduino pour un usage futur…

Je n’ai pas mis le schéma des capteurs. Vous pouvez en trouver plein sur le playground arduino ici. Il suffit d’utiliser une prise jack 3.5mm male et de la brancher sur la prise SENSORS. Vous avez alors VCC,  GND, DATA. Où DATA est un voltage entre 0 et 5 v.

Je ne suis pas sûr que mon système soit utilisable tel quel chez vous, mais vous pouvez vous en inspirer pour créer le votre. En tout cas, chez moi ça marche très bien :-)

Pour ce qui est du code, le voici:

[code]

#include <LCD4Bit.h>

//BUG ?
#undef int()
// END BUG
#include <stdio.h>

LCD4Bit lcd = LCD4Bit(2);

//#define DEBUG 1

// global defs
#define shootPin  11
#define sensorPin 4
#define bt1Pin 3
#define bt2Pin 4
#define bt3Pin 5
#define bt4Pin 6
#define ledPin 13 //digital

#define MAXMENU 4

#define MENUSENSOR 1
#define MENUSTROBEDELAY 2
#define MENURUN 3

#define MODESENSOR 1

#define NO 0
#define YES 1
#define TEST 2

#define SOUNDSENSOR 0
#define IRSENSOR 1
#define CONTACTSENSOR 2
#define LIGHTSENSOR 3

volatile unsigned int menu0Pos = MENUSENSOR;
volatile unsigned int debounce = 0;
volatile unsigned int modeSensor = 0;
volatile unsigned int modeDrop= 0;
volatile unsigned int modeApp = MODESENSOR;
volatile unsigned int sensorType = IRSENSOR;
volatile unsigned int firstPass = 0;
volatile unsigned int sndLevel = 0;

volatile int strobeDelay = 10;

void setup() {
pinMode(ledPin,OUTPUT);
pinMode(shootPin,OUTPUT);
pinMode(bt1Pin,INPUT);
pinMode(bt2Pin,INPUT);
pinMode(bt3Pin,INPUT);
pinMode(bt4Pin,INPUT);
setLed(1);
lcd.init();

/*lcd.commandWrite(0x0F);//cursor on, display on, blink on.  (nasty!)
*/
lcd.clear();
lcd.printIn("equinoxefr.org");
lcd.cursorTo(2, 0);  //line=2, x=0.
lcd.printIn("Photo lab v0.3");
delay(2000);
fillLine(2,"FW Trigger");
delay(2000);
lcd.clear();
setLed(0);
#ifdef DEBUG
Serial.begin (9600);
Serial.println("start");                // a personal quirk
#endif
}

void loop() {
int val=0;
int keyFactor=1;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  SENSOR SECTION
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (modeSensor)
{
while (1)
{
val=analogRead(sensorPin);
switch (sensorType)
{
case LIGHTSENSOR:

if (val > 500)
{
shoot();
}
//      char buffer[50];
//      strobeDelay=getValue(strobeDelay,-1,9999);
//      itoa(strobeDelay,buffer,DEC);
//      fillLine(2,buffer);
break;

case IRSENSOR:

if (val < 900)
{
shoot();
}
//      char buffer[50];
//      strobeDelay=getValue(strobeDelay,-1,9999);
//      itoa(strobeDelay,buffer,DEC);
//      fillLine(2,buffer);
break;

case SOUNDSENSOR:
if (firstPass)
{
fillLine(2,"Getting snd level");
sndLevel=soundLevel();
clearLcdLine(2);
firstPass=0;
}
val = analogRead(sensorPin);

if ((val > (sndLevel + 40)) && (val < 1024))
{
shoot();
}

break;

case CONTACTSENSOR:
if ( val < 500)
{
shoot();
}
break;
}
}
}

/*
#ifdef DEBUG
Serial.println(menu0Pos,DEC);
#endif
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  MENU SECTION
/////////////////////////////////////////////////////////////////////////////////////////////////////////////

switch (menu0Pos)
{
case MENUSTROBEDELAY:
fillLine(1,"Strobe delay ms");
modeSensor=0;
strobeDelay=getValue(strobeDelay,-1,9999);
if (strobeDelay==-1)
{
fillLine(2,"not used");
}
else
{
char buffer[50];
itoa(strobeDelay,buffer,DEC);
fillLine(2,buffer);
}
break;
case MENUSENSOR:
fillLine(1,"Select sensor");
sensorType=getValue(sensorType,0,3);
switch(sensorType)
{
case SOUNDSENSOR:
fillLine(2,"SOUND");
firstPass=1;
break;
case IRSENSOR:
fillLine(2,"IR BARRIER");
break;
case CONTACTSENSOR:
fillLine(2,"CONTACT");
break;
case LIGHTSENSOR:
fillLine(2,"IR LIGHT");
break;
}
//digitalWrite(ledPin, HIGH);
modeSensor=0;
break;

case MENURUN:
if (!modeSensor)
{
fillLine(1,"***SHOOT MODE***");
}
modeSensor=1;
break;
}
getMenu();
}

//
//  soundLevel()
//
int soundLevel()
{
int value=analogRead(sensorPin);

Serial.println("Getting sound level...");
for(int i=0; i < 50 && !modeSensor; i++)
{
value = ( value + analogRead(sensorPin) ) / 2;
delay(50);
}
Serial.println("Done!");

return value;

}

void clearLcdLine(int line)
{
lcd.cursorTo(line, 0);
lcd.printIn("                     ");
}

void fillLine(int line,char* str)
{
char buffer[21];
int len=strlen(str);
for (int i=0;i<20;i++)
{
if (i < len)
{
buffer[i]=str[i];
}
else
{
buffer[i]=' ';
}
}
lcd.cursorTo(line,0);
lcd.printIn(buffer);
}

void shoot()
{
if (strobeDelay > 0 )
{
delay(strobeDelay);
}
digitalWrite(shootPin,HIGH);
delay(10);
digitalWrite(shootPin,LOW);
fillLine(2,"Shoot !");
digitalWrite(ledPin,HIGH);
delay(3000);
digitalWrite(ledPin,LOW);
clearLcdLine(2);

}

void getMenu()
{
int bt1=digitalRead(bt3Pin);
int bt2=digitalRead(bt4Pin);

if (!bt1 && !bt2)
{
return;
}

if (bt1 && menu0Pos < MAXMENU)
{
menu0Pos++;
}
if (bt2 && menu0Pos > 0)
{
menu0Pos--;
}

}

int getValue(int value, int mini, int maxi)
{
unsigned int keyFactor=1;
int bt1=digitalRead(bt1Pin);
int bt2=digitalRead(bt2Pin);

if  (value < 50 )
{
keyFactor=1;
}
else
{
if (value >= 50 )
{
keyFactor=10;
}
}
if  ( bt1 )
{
value+=keyFactor;
}
if  ( bt2 )
{
value-=keyFactor;
}

if ( value <= mini)
{
value=mini;
}
else
{
if (value >= maxi)
{
value=maxi;
}
}
/*
if ( bt1 && bt2 )
{
modeSensor=0;
fillLine(2,"switch off");
}
*/
return value;

}

void setLed(int value)
{
if (value)
{
digitalWrite(ledPin,HIGH);
}
else
{
digitalWrite(ledPin,LOW);
}
}
[/code]

sept 052008

Si comme moi vous souhaitez utiliser une périphérique de capture video Dazzle DVC 100, il faut un tout petit peu d’huile de coude, le module em28xx présent avec ubuntu hardy ne reconnaissant pas ce matériel.

Après insertion de la prise usb, la commande lsusb nous donne le type de périphérique:

[code]

Bus 005 Device 003: ID 2304:021a Pinnacle Systems, Inc. [hex]

[/code]

Par défaut, seule l’acquisition audio est prise en compte, la vidéo elle, n’est pas gérée.

Après quelques recherches sur notre ami Google, il s’avère que ce matériel est géré par le projet v4l-dvb dans ses dernières versions.

Dans une console, installons les outils nécessaires à la compilation du module.

[code]

sudo apt-get install mercurial build-essential

[/code]

ensuite, nous sommes prêts pour récupérer les sources du module à l’aide de mercurial.

[code]

mkdir ~/src

cd ~/src

hg clone http://linuxtv.org/hg/v4l-dvb

cd v4l-dvb

[/code]

Nous voilà prêts pour la compilation.Le -j2 passé en paramètre au make permet d’utiliser les multicoeurs (2) des processeurs récents. Si vous avez un mono processeur classique, un simple make suffit.

[code]

make -j2

....

CC      /home/pierre/src/v4l-dvb/v4l/zr36060.mod.o
LD [M]  /home/pierre/src/v4l-dvb/v4l/zr36060.ko
CC      /home/pierre/src/v4l-dvb/v4l/zr36067.mod.o
LD [M]  /home/pierre/src/v4l-dvb/v4l/zr36067.ko
CC      /home/pierre/src/v4l-dvb/v4l/zr364xx.mod.o
LD [M]  /home/pierre/src/v4l-dvb/v4l/zr364xx.ko
make[2]: Leaving directory `/usr/src/linux-headers-2.6.24-19-generic'
./scripts/rmmod.pl check
found 261 modules
make[1]: quittant le répertoire « /home/pierre/src/v4l-dvb/v4l »
[/code]

Tout a l’air OK, lançons maintenant l’installation des modules pour le noyau courant.

[code]

pierre@vbox:~/src/v4l-dvb$ sudo make install
make -C /home/pierre/src/v4l-dvb/v4l install
make[1]: entrant dans le répertoire « /home/pierre/src/v4l-dvb/v4l »
Stripping debug info from files
-e
Removing obsolete files from /lib/modules/2.6.24-19-generic/kernel/drivers/media/video:

-e
Removing obsolete files from /lib/modules/2.6.24-19-generic/kernel/drivers/media/dvb/frontends:

Installing kernel modules under /lib/modules/2.6.24-19-generic/kernel/drivers/media/:
dvb/dvb-usb/: dvb-usb-dtv5100.ko dvb-usb-opera.ko dvb-usb-cxusb.ko
dvb-usb-vp7045.ko dvb-usb-af9005-remote.ko dvb-usb-ttusb2.ko
....

....
video/em28xx/: em28xx-dvb.ko em28xx.ko
video/pvrusb2/: pvrusb2.ko
radio/: dsbr100.ko radio-maestro.ko radio-zoltrix.ko
radio-terratec.ko radio-aimslab.ko radio-maxiradio.ko
radio-gemtek.ko radio-trust.ko radio-sf16fmr2.ko
radio-typhoon.ko radio-cadet.ko radio-aztech.ko
radio-si470x.ko radio-sf16fmi.ko radio-rtrack2.ko
radio-gemtek-pci.ko
video/uvc/: uvcvideo.ko
dvb/ttusb-budget/: dvb-ttusb-budget.ko
video/pwc/: pwc.ko
video/zc0301/: zc0301.ko
video/ovcamchip/: ovcamchip.ko
video/au0828/: au0828.ko
/sbin/depmod -a 2.6.24-19-generic
make[1]: quittant le répertoire « /home/pierre/src/v4l-dvb/v4l »
pierre@vbox:~/src/v4l-dvb$

[/code]

Maintenant, à l’insertion du boitier Dazzle, dmesg est beaucoup plus compatissant :-)

[code]

[ 5747.848507] em28xx new video device (2304:021a): interface 0, class 255
[ 5747.848515] em28xx Has usb audio class
[ 5747.848517] em28xx #0: Alternate settings: 8
[ 5747.848519] em28xx #0: Alternate setting 0, max size= 0
[ 5747.848521] em28xx #0: Alternate setting 1, max size= 1024
[ 5747.848524] em28xx #0: Alternate setting 2, max size= 1448
[ 5747.848526] em28xx #0: Alternate setting 3, max size= 2048
[ 5747.848528] em28xx #0: Alternate setting 4, max size= 2304
[ 5747.848531] em28xx #0: Alternate setting 5, max size= 2580
[ 5747.848533] em28xx #0: Alternate setting 6, max size= 2892
[ 5747.848535] em28xx #0: Alternate setting 7, max size= 3072
[ 5747.848727] em28xx #0: em28xx chip ID = 18
[ 5748.434840] saa7115' 0-0025: saa7113 found (1f7113d0e100000) @ 0x4a (em28xx #0)
[ 5749.203790] em28xx #0: i2c eeprom 00: 1a eb 67 95 04 23 1a 02 12 00 11 03 98 10 6a 2e
[ 5749.203803] em28xx #0: i2c eeprom 10: 00 00 06 57 4e 00 00 00 60 00 00 00 02 00 00 00
[ 5749.203821] em28xx #0: i2c eeprom 20: 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 5749.203847] em28xx #0: i2c eeprom 30: 00 00 20 40 20 80 02 20 10 01 00 00 00 00 00 00
[ 5749.203857] em28xx #0: i2c eeprom 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 5749.203873] em28xx #0: i2c eeprom 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 5749.203899] em28xx #0: i2c eeprom 60: 00 00 00 00 00 00 00 00 00 00 2e 03 50 00 69 00
[ 5749.203924] em28xx #0: i2c eeprom 70: 6e 00 6e 00 61 00 63 00 6c 00 65 00 20 00 53 00
[ 5749.203948] em28xx #0: i2c eeprom 80: 79 00 73 00 74 00 65 00 6d 00 73 00 20 00 47 00
[ 5749.203974] em28xx #0: i2c eeprom 90: 6d 00 62 00 48 00 00 00 10 03 44 00 56 00 43 00
[ 5749.204000] em28xx #0: i2c eeprom a0: 31 00 30 00 30 00 00 00 32 00 30 00 33 00 35 00
[ 5749.204025] em28xx #0: i2c eeprom b0: 36 00 30 00 37 00 35 00 31 00 33 00 34 00 31 00
[ 5749.204051] em28xx #0: i2c eeprom c0: 30 00 32 00 30 00 30 00 30 00 31 00 00 00 32 00
[ 5749.204075] em28xx #0: i2c eeprom d0: 33 00 31 00 32 00 33 00 00 00 00 00 00 00 00 00
[ 5749.204100] em28xx #0: i2c eeprom e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 5749.204123] em28xx #0: i2c eeprom f0: 00 00 00 00 00 00 00 00 0a 07 d4 04 31 62 5d 0e
[ 5749.204150] EEPROM ID= 0x9567eb1a, hash = 0x72aaae84
[ 5749.204153] Vendor/Product ID= 2304:021a
[ 5749.204156] AC97 audio (5 sample rates)
[ 5749.204160] 300mA max power
[ 5749.204163] Table at 0x06, strings=0x1098, 0x2e6a, 0x0000
[ 5749.788387] em28xx #0: V4L2 device registered as /dev/video0 and /dev/vbi0
[ 5749.788396] em28xx #0: Found Pinnacle Dazzle DVC 90/DVC 100
[ 5749.788468] em28xx audio device (2304:021a): interface 1, class 1
[/code]

Voilà, c’est terminé, vous pouvez maintenant choisir n’importe quelle application supportant les périphérique v4l. Pensez par contre a refaire un make && make install à chaque mise à jour de votre noyau.

P.S, pour faire ce tuto, j’en ai profité pour faire les tests sur une ubuntu installée sur virtualbox 2, bien pratique pour être sur d’avoir une Ubuntu toute propre.

juil 022008

Voici comment connecter très facilement un PC Linux ( Ubuntu 8.04 sur eeepc ) à internet avec un téléphone 3G.

nokia n95

J’ai un nokia N95 qui est parfaitement supporté sur Ubuntu. Pour se connecter, j’utilise le cable USB, mon EEEPC n’ayant pas de bluetooth. Lors du branchement du téléphone, il faut sélectionner le mode

PC SUITE sur NOKIA. Sous Linux, un petit dmesg nous en dit plus:

[code]

[   65.528724] usb 2-1: new full speed USB device using uhci_hcd and address 2
[   65.545353] usb 2-1: configuration #1 chosen from 1 choice
[   67.050935] cdc_acm 2-1:1.10: ttyACM0: USB ACM device
[   67.060398] usbcore: registered new interface driver cdc_acm
[   67.060858] /home/adamm/git/ubuntu-hardy/debian/build/custom-source-eeepc/drivers/usb/class/cdc-acm.c: v0.25:USB Abstract Control Model driver for USB modems and ISDN adapters
[   67.094186] usbcore: registered new interface driver cdc_ether
[   67.104548] usb 2-1: bad CDC descriptors
[   67.104988] usbcore: registered new interface driver rndis_host

[/code]

Pour établir la connexion, nous avons besoin de wvdial.

[code]

sudo apt-get install wvdial

[/code]

Ensuite, pour le paramétrer, créez le fichier /etc/wvdial.conf contenant ceci:

[code]

[Dialer Defaults]
Modem = /dev/ttyACM0
Baud = 460800
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init5 = AT+CGDCONT=1,"IP","orange";
ISDN = 0
Modem Type = Analog Modem
Phone = *99***1#
username = orange
password = orange
Stupid Mode = 1

[/code]

Pour établir le lien, branchez le téléphone puis tapez

[code]

sudo wvdial

[/code]

et hop à vous internet mobile.

Je précise que j’ai un abonnement Orange et que ça marche sans surfacturation (Internet Max). Le même principe marche chez SFR (en modifiant le useragent du navigateur) et Bouygues. S’il n’y a pas d’abus avec ces connexions, il n’y a pas vraiment de raison que les opérateurs verrouillent le système.