Enviat per: Matias | 4 Novembre 2010

Test de color

Després de poder implementar el PWM i de controlar la freqüència de so que s’ha de generar, és l’hora de començar a fer test amb els colors que capta la càmera i mapejar-los a l’escala de sons que ha definit en Neil, que considera adient per identificar els colors:

Escala sonocromàtica pura

#FF0000   VERMELL 363.7978807091713 Hz
#FF7F00    TARONJA 30º 440.19543565809727 Hz
#FFFF00  GROC 60º 462.02330850064754 Hz
#00FF00  VERD 120º 478.39421313256025 Hz
#00FFFF  CIAN 180º 551.1537892743945 Hz
#0000FF  BLAU 240º 573.8911568187177 Hz
#7F00FF  VIOLETA 270º 607.5424607843161 Hz
Per veure com capta els colors la camara i els transforma en sons, vegem el següent video:


El següent pas és començar a fer test del color, i provar amb colors més naturals, intentant ajustar-los al color més pròxim.
Enviat per: Matias | 29 Agost 2010

Interrupcions

Ja hem vist el funcionament del rellotge del processador, i també hem parlat de com volem generar el PWM. Però el PWM no s’ha de programar mitjançant retards en el rellotge (amb delays de ms, per exemple), perquè sinó tindrem un bucle que ocuparà gairebé el 100% del temps de processador només esperant, així que s’han d’utilitzar les interrupcions de rellotge.

La idea és modificar l’ample de pols a cada periode del PWM, de manera que acabem generant una sinusoidal com he explicat anteriorment. Per tant cal aconseguir que a cada T (periode) del PWM es generi una interrupció que ens permeti reconfigurar els registres necessaris per modificar l’ample de pols. D’aquesta manera, només ocuparem un temps molt parcial del processador, i podrem utilitzar la resta del temps (que serà molt) per processar les imatges, que és l’altre part que ens falta.

El rellotge té les seves pròpies interrupcions, però resulta que el PWM també porta incorporats uns registres per servir interrupcions a un nivell diferent de les del rellotge, i aquestes són les que hem de tractar. Per utilitzar les interrupcions només hem d’entendre la part de registres que ho configura, i posar els valors correctes:

Primer de tot hem de configurar el periode del PWM. Tenim un preescaler que fa de divisor pels tics de rellotge i el match register és el que marca el final del comptatge. Quan el comptador (que incrementa a cada valor de preescaler) arriba al valor del match register, es produeix l’acció que haguem configurat (es pot resetejar, parar, fer interrupcions…). Per tant primer configurem un periode qualsevol:

REG(PWM0_PR) = 1000;
REG(PWM0_MR0) = 45900;

Amb aquests valors aconseguim més o menys una interrupció cada segon. Perquè el valor de MR0 es faci efectiu, hem d’actualitzar el bit del registre PWM0_LER. Això ho fem posant-ho a 1, ja que és el primer bit del registre.

REG(PWM0_LER) = 1;

Per veure una mica més com funciona, vegem la imatge de blocs de PWM:

L’actualització del Latch Register es necessaria per passar els valors del Match Register X al Shadow Register X, on es farà efectiu el valor que s’utilitzarà per les sortides del PWM que es veuen a la dreta.

Un cop posat el període del PWM, encara hem de configurar un parell de registres més:

REG(PWM0_TCR) = 0x01;

PWM0_TCR serveix per indicar quin us fem dels comptadors. Necessitem posar el primer bit a 1, perquè així el timer i el preescaler s’activen per començar a comptar, sinó estan aturats.

REG(PWM0_MCR) = 0x03;

PWM0_MCR serveix per configurar les accions adients quan es crea un match en els registres de Match del PWM. En el nostre cas, el que volem és que es generi una interrupció, però a més a més, també volem que els comptadors es posin a 0, perquè sinó, no tornaran a fer match mai (o almenys fins que desbordi el comptador i torni a començar…). Així doncs, posem els 2 primers bits a 1 (0x03) de manera que creem interrupció i fem un reset als comptadors cada cop que hi ha un match.

Ara ja tenim configurat el PWM com voliem, però ara necessitem capturar les interrupcions en el software, anem-ho a veure:

El processador té la llibreria de funcions a la carpeta lpc2106-cmucam3. Nosaltres, de tots els fitxers, editarem el “interrupt.c” per proporcionar un punt d’accés al nostre codi. En aquest fitxer, hi ha una rutina “interrupt()” que es genèrica per totes les interrupcions del processador, i allà, comprovant registre per registre, es van determinant de quin tipus de interrupcions es tracten. Així doncs, nosaltres capturarem les interrupcions del PWM, i cridarem una funció que estarà declarada en el nostre codi, de manera que no haurem de modificar mai més el fitxer “interrupt.c”. És el seguent:

if (REG (PWM0_IR) == 0x1) {

pwm_interrupt();
REG (PWM0_IR) = 0x01;

}

Comprovem el registre PWM0_IR, en el bit 0, ja que tractem les interrupcions que genera el match register 0, i si és d’aquest tipus entra i crida la nostra funció pwm_interrupt(). Un cop fet el que volem dins la funció, resetejem el bit d’interrupció per indicar que ja s’ha servit (en el mateix registre IR, posant el bit 0 a 1)  i esperarem a que ens arribi la pròxima.

Finalment en el nostre codi, posem per exemple un flag que ens vagi encenent i apagant un led de la placa a cada interrupció, i veiem clarament com funciona.

La següent part serà veure a quant podem ajustar la freqüència de les interrupcions, que serà en definitiva la resolució de la nostra senyal, i modificar l’ample de pols a cada interrupció.

Enviat per: Matias | 4 Agost 2010

PCLK

En aquesta entrada explico a quina freqüència funciona el PWM, sense modificar de moment cap paràmetre. Per entendre-ho, s’ha de veure qui controla els impulsos del PWM. Llegint a la documentació, trobem que el PWM va dirigit per el PCLK,  o sigui que hem d’esbrinar d’on surt aquest valor.

La font que controla el rellotge del sistema és un cristall de quars que funciona a 14Mhz, en la documentació diu que funciona entre 10Mhz i 25Mhz, però en el cristall posa escrit exactament 14Mhz. Ara ens fixem en el següent esquema:



FOSC és la freqüència d’oscilació del cristall. A partir d’aquí, es posa un circuit anomenat PLL (Phase-Locked Loop) per poder controlar la freqüència que rebrà el processador, que és CCLK (la senyal que hi ha al final del circuit). Si el PLL no està activat, veiem que el processador rep directament el FOSC com a font de rellotge, però sinó hi ha una cosa a tenir en compte. El PLL conté un multiplicador (controlat pels bits MSEL) que fa que FOSC es multipliqui. Mirant els valors dels registres a l’engegar la placa descobreixo que MSEL = 3, per tant calculem CCLK de la forma:

CCLK = M * FOSC = 3 * 14 = 42Mhz

Un cop sortim del PLL, tenim el CCLK resultant (que és pel processador) però nosaltres volem el PCLK (que esta dedicat a dispositius externs, recordem que això és referent a la documentació del processador, per tant dispositius externs ens referim a tot el que hi ha al voltant del processador, la memòria, la SD, el PWM… i com veiem en la seguent imatge, el PCLK surt d’un block anomenat VPB Divider.

El VPB Divider esta disenyat perque es dona per suposat que els dispositius externs al processador no funcionen a màxima freqüència com el processador, sinó que poden anar tranquilament a la meitat o a un quart de freqüència i estalviar així energia i potència. Així doncs esta disenyat per posar-ho igual, a la meitat, o a un quart de freqüència del processador mitjançant un registre que ens ho indica i que jo he mirat a l’engegar la placa quin valor tenia. VPB Divider esta configurat en el meu cas a la mateixa freqüència que el processador, per tant PCLK = 42 MHz de moment.

Encara no hem acabat! Sembla evident que el PWM no funciona a 42MHz, encara falta tenir en compte els preescalers i els comptadors del Timer i del PWM, ja que cadascún en té un d’individual. Segurament no el podrem baixar molt baix, perquè el sistema necessita tics de rellotge per tractar altres events (canvis de context, interrupcions, etc..) per tant ho hem de comprovar, tot i que segur que ens quedarà una freqüència que s’anirà cap als KHz.

Enviat per: Matias | 4 Agost 2010

PWM

Donat que la plataforma de visió de CMUCam3 no disposa de sortida d’audio directe, em toca generar la senyal d’audio fent ús del PWM.
El PWM (Pulse Width Modulation), com el seu nom indica, és la tècnica de modular l’ample del puls (que direm duty cicle) per tal de donar més o menys potència a la senyal de sortida.

PWM

Posem que tenim un PWM amb duty cicle al 50% en un voltatge de 5V, la senyal resultant serà un senyal constant de 2,5V.

El PWM esta implementat en la plataforma, dissenyat amb la intenció de controlar servos per controlar robots, ja que funciona amb la mateixa corrent d’entrada (només té una font adicional per si de cas volem més voltatge) i utilitza el timer del processador per funcionar. Però el podem utilitzar per generar so? Com? L’objectiu és aconseguir un sinus, que és el to pur d’un so.

Hi ha dos alternatives, amb els seus avantatges i inconvenients:

  • Electrònica: Si aconseguim generar un PWM a una frequència d’uns 440 Hz, que és senzill, ja tindriem la nota “LA”, però al ser una senyal quadrada, tenim el problema de que se sent molt malament, els pics de la senyal fa que hi hagi molta interferència i que se sentin cops en el so. La manera d’arreglar això seria posant un petit circuit RC que absorbís lentament la càrrega del pols, per generar una corba en comptes d’una senyal cuadrada, però només aconseguim una forma de “dent de tauró” per dir-ho així, puja fent corba lentament, però baixa fent corba ràpidament, cosa que també genera el cop en el so, i encara no sona del tot net.
  • Software: Per software es pot aconseguir controlar la forma del senyal de sortida a la perfecció, modificant el duty cicle en el moment adequat i fer-ho incrementalment com si es tractés d’una integració, es dona poc duty cicle si es vol pujar poc, i es dona molt duty si es vol pujar de cop. El problema d’aquest mètode és la resolució. Si volem generar així el senyal de 440Hz per exemple, necessitem X divisions a cada periode del senyal per poder controlar el PWM. Quan més gran sigui X, més fina sortirà la senyal del sinus, és evident que amb X=2 no fariem res, potser sortirà d’uns X=100 mínim, així que hauriem d’aconseguir fer anar el PWM a 44KHz.

Així doncs, de moment optaré per la segona solució, controlar-ho per software però s’haurà de tenir una resolució del PWM a 44Khz com a mínim, hauré de mirar fins a on ens permet arribar el clock del processador.

Enviat per: Matias | 25 Març 2010

Botó

Abans de provar la càmara, volia mirar de captar la pulsació del botó ISP. Pensava que seria un moment.. però sembla ser que no.

Per captar el valor del botó, es fa servir la funció cc3_button_get_state () que si val cert, es que el boto esta actiu, tant facil com això. Curiosament jo ho he provat al primer intent, i no llegia res.

M’he posat a mirar el codi de les funcions, per saber realment que fa, i aquí esta el codi:

bool cc3_button_get_state (void)
{
if (!_cc3_button_trigger) {
// button has not been pressed
return false;
}

// otherwise, it has been pressed, and it's in GPIO mode
return !(REG (GPIO_IOPIN) & _CC3_BUTTON);
}

bool cc3_button_get_and_reset_trigger (void)
{
bool result = _cc3_button_trigger;
_cc3_button_trigger = false;
// reset interrupt
if (result) {
enable_button_interrupt();
}

return result;
}

Fixem-nos que la funcio cc3_button_get_state només retorna el valor real del botó (mitjançant uns flags) si la variable cc3_button_trigger es true. Pero curiosament, mai s’aconsegueix posar a true, i si fem servir la funció seguent cc3_button_get_and_reset_trigger() es posa sempre a false, i despres al llegir sempre retorna false.
Hi hauria d’haver alguna funcio que poses _cc3_button_trigger = true, i una funcio al fitxer d’interrupcio (que es crida a la inicialitzacio del sistema) enable_button_interrupt() l’únic que fa es posar bé els flags de hardware, pero no modifica a _cc3_button_trigger.

Per tant he modificat la funcio de reset per posar-lo a true, he recompilat el cc3, i ara evidentment em funciona, pero continuo sense entendre perquè he hagut de modificar-ho.

He penjat un post a la web de CMUCam per veure si em treuen el dubte: Post

Almenys el boto se que funciona i no es problema de hardware.

Enviat per: Matias | 21 Març 2010

Memòria SD

Avui em volia dedicar a comprovar exactament com funciona la memòria SD en la placa, i com puc guardar i llegir dades fent un petit programa de prova.

Per començar he llegit la documentació seguent que em proporciona la pàgina oficial: http://cmucam.org/wiki/mmc

Simplement comentar un parell de característiques importants a tenir en compte:

  • la CMUCam es comunica amb la SD mitjançant una interficie SPI http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
  • Necessitem tenir la SD amb un format FAT de 16 bits (no suporta FAT de 32 bits, ni altres de linux com la ext3)
  • Els subdirectoris emmagatzemats a la SD no permeten més de 254 fitxers

Per provar la SD, mirem de fer un petit programa, que escrigui alguna cosa en un fitxer, i després poguem consultar que s’ha escrit correctament:

#include "cc3.h"

int main (void)
{
	FILE *fp;
	cc3_uart_init (0, CC3_UART_RATE_115200, CC3_UART_MODE_8N1,
                 CC3_UART_BINMODE_TEXT);
	printf("Programa de prova per escriure a SD\n");

	// Iniciem el sistema de fitxers
	cc3_filesystem_init ();
	printf("- Sistema de fitxers inicialitzat!\n");

	// Obrim un fitxer a la SD
	fp = fopen ("c:/prova.txt", "w");
	if (fp == NULL) {
		perror ("Ha fallat a l'obrir el fitxer");
	} else {
		fprintf( fp, "Hola! Això és un text de prova\n" );
		fclose (fp);
		printf("\t..Fitxer escrit!\n");
	}
	while(true);
}

La funció cc3_init_filesystem, esta implementada en el drivers.c de les llibreries del cc3, i el que fa es reservar l’espai com a dispositiu per la SD, és a dir, si no inicialitzem això, no podrem accedir a la SD.

Seguidament fem servir les funcions típiques de C fopen, fprintf, fclose per manegar el fitxer.

Les linies marcades en blau són coses que he arreglat posteriorment de provar el programa, perquè no sabia que eren necessàries, per exemple:

  • Resulta que la placa executa repetidament el codi, si no hi ha un control sobre el codi, és a dir, si no es programa que el codi tingui un cicle de vida “infinita” per dir-ho així, amb un bucle, la placa finalitza el codi i al cap d’un cert temps el torna a executar automàticament (hauré d’estudiar millor aquesta part). És a dir que escrivia més o menys cada segon a la SD, per això he posat un while.
  • També cal inicialitzar el port UART, perquè sino no pot enviar comunicacions al minicom mitjançant la sortida estandard.

Per compilar el programa, he hagut de crear una mica de “workspace” per treballar, ja que per generar el .hex, necessito accedir a un makefile que porta el compilador, i que no tenia el path correcte, l’he modificat i cap problema, la compilació és aquesta:

Seguidament he pujat el .hex com ja és habitual a la placa, i he engegat el minicom per comprovar que funciona:

Bé! Ja hem escrit al fitxer sembla! Ho he comprovat posant la SD al PC i assegurant-me que el fitxer era correcte.

Això és tot de moment, sembla que la SD funciona, i ja hem vist les quatre restriccions necessàries per fer-la funcionar correctament. El pròxim dia segurament ja començaré a mirar la càmara, que portarà molta més feina.

Enviat per: Matias | 9 Març 2010

Primer contacte

He aconseguit posar-me en contacte amb la placa per primer cop:

Per començar, he tingut que buscar un adaptador AC/DC per poder-ho conectar a la corrent. He aconseguit un de voltatge variable que em dona els 5 volts que necessito per alimentar la placa. He fet una connexió més o menys fiable amb la entrada de corrent de la placa.

Després he comprat també un conversor RS232 a USB, perquè volia treballar desde el portàtil… i es que els portàtils ja no estan preparats per aquests ports tant antics xD, gràcies a Ubuntu ja em detecta el cable correctament i no he d’instalar el CD que em venia amb el cable!!! (un CD per un cable? :S).

Tinglado

Un cop conectada, l’he posat en marxa i se li han encès uns leds que ni sabia que tenia! (encara no els havia vist a les especificacions). Disposa de 4 leds, un verd, un vermell, i dos de grocs.

– Per programar la placa, s’ha d’encendre pitjant primer el botó ISP i després encenent la placa (mode programació)

– Per entrar en execució, s’ha d’encendre directament (mode execució)

Leds

Seguidament m’he preparat per provar el primer programa, a veure com ho havia de fer. Simplement he seguit unes instruccions per preparar tot l’entorn en linux http://cmucam.org/wiki/Linux-Quick-Start (ja que treballo amb Ubuntu 9.10), molt ben documentades, m’han permès seguir l’instalació sense problemes fins el punt de carregar el programa en hexadecimal a la placa.

Simplement, el problema que he tingut ha sigut que, per carregar el programa, havia de fer servir el programa lpc21isp (que fa de bootloader del codi per plaques Phillips o ARM, com aquesta) amb aquesta ordre:

./lpc21isp ../cc3/projects/cmucam2/cmucam2_lpc2106-cmucam3.hex /dev/ttyS0 115200 14746
I aquí estava el problema, que l’estava redirigint al port sèrie pensant que l’Ubuntu ja sabia que tenia un cable conversor RS232 a USB, i que era evident que s’havia de redireccionar per allà! En fi, que s’ha de redireccionar a /dev/ttyUSB0.
Per fi vaig poder carregar el codi, adjunto unes pantalles del que va passar.
Primer ProgramaPrimer contacte

Simplement mostra la versió de la càmara. Ara em dedicaré a posar algun programa més complex, on pugui fer funcionar tota la placa (pulsador, memòria SD, i el més important, la càmara).

Enviat per: Matias | 7 Març 2010

Benvinguts!

Benvinguts al blog del Eyeborg 2.0! Sóc en Matias Lizana i aquest és el meu projecte final de carrera com a estudiant d’informàtica.

En aquest blog aniré publicant entrades sobre el desenvolupament d’aquest projecte, així com problemes que he anat trobant per guardar-los per futures referències.

Categories