Flappy Chip (joc cu Arduino Uno)

Autor - Stelian -17/07/2014-

Flappy Chip este un joc care ruleaza pe Arduino Uno (sau atmega328). Scopul jocului este evitarea coliziunii cu tuburile care stau in calea chip-ului, prin apasarea unui buton care face ca chip-ul sa faca un salt (altfel pierde inaltime treptat). Scorul reprezinta numarul perechilor de tuburi evitate.




Hardware

Afisarea se face pe un ecran recuperat dintr-un telefon Nokia 3310. Ecranul se alimenteaza de la pinul de 3,3 V de pe placa Arduino. Conexiunea la placa (sau microcontroller) se realizeaza prin intermediul a cinci divizori rezistivi care au ca scop schimbarea nivelului logic din 5 v in 3,3 V. Pinii folositi in acest scop sunt de la 3 pana la 7 si indeplinesc urmatoarele functii :

  • pin 3 – LCD reset (RST)
  • pin 4 – LCD chip select (CS)
  • pin 5 – Data/Command select (D/C)
  • pin 6 – Serial data out (DIN)
  • pin 7 – Serial clock out (SCLK)

Butonul este conectat intre pinul digital 2 si masa, cu pull-up intern activat. Astfel, la trecerea pinului din 1 logic in 0 se declanseaza o rutina de intrerupere care modifica pozitia chip-ului.



Software


Fiecare element grafic a fost desenat in Paint, salvat ca bitmap monocrom si transformat in valori hexazecimale

folosint programul Image2Code. Imaginile sunt stocate in memoria Flash. Pentru a putea afisa elemente in fata fundalului sunt utilizate bitmap-uri ,,pline” de culoare neagra, afisate negativ pentru a  ,,sterge”  fundalul din spatele obiectului ce urmeaza a fi afisat. Pentru a simplifica implementarea in software a comunicarii cu driverul de display, programul are la baza bibliotecile Adafruit PCD8544 si   GFX.

Dupa afisarea imaginii de start, se asteapta apasarea butonului pentru a incepe jocul. Apoi, este activata rutina de intrerupere responsabila de functionarea butonului si incepe executia gameloop-ului cat timp chip-ul este ,,in viata”. La fiecare parcurgere a buclei se sterge vechea imagine de pe ecran, apoi este afisat fundalul. Numarul maxim de tuburi care apar la un moment dat in joc este de 4 perechi, deoarece au fost declarate 4 seturi de variabile in acest scop. Jocul incepe cu o singura pereche. Treptat, distanta dintre tuburi este redusa atat pe verticala cat si pe orizontala ,pentru a mari dificultatea, ceea ce conduce la introducerea mai multor perechi de tuburi in joc. O serie de if-uri verifica daca vreuna dintre perechi a iesit din ecran, iar in caz afirmativ ii atribuie variabilei corespunzatoare valoarea false. Apoi, daca perechea de tuburi care se afla cel mai aproape de marginea din dreapta a ecranului a ajuns la distanta potrivita fata de aceasta margine, este introdusa o noua pereche de tuburi prin reinitializarea variabilelor corespunzatoare. O alta serie de if-uri muta tuburile afisate cu

un pixel spre stanga. Apoi, sunt afisate tuburile si scorul si se compara coordonatele tuburilor cu coordonatele chip-ului, pentru a stabili daca s-a produs o coliziune, caz in care procedura dead face ca chip-ul sa cada, dupa care executia iese din gameloop. De asemenea, coliziunea cu marginile ecranului cauzeaza terminarea jocului. In final, scorul este incrementat de cate ori chip-ul trece de o pereche de tuburi, iar variabila care  reprezinta pozitia chip-ului este incrementata pentru a-l face sa cada. Delay-ul de la sfarsitul buclei ii da utilizatorului timp de reactie, stabilind viteza la care ruleaza jocul. Dupa iesirea din gameloop, rutina de intrerupere este dezactivata, iar scorul actual este comparat cu scorul record (daca exista un astfel de scor stocat in memoria EEPROM). Daca nu exista un record stocat in memorie, sau daca scorul actual este mai mare, un nou record este scris in memoria EEPROM pentru a se pastra dupa pierderea alimentarii. Pentru a evita deteriorarea memoriei, un algoritm de uzura echilibrata scrie scorul la o adresa diferita de fiecare data.


Cod sursa


/*Written by Stelian Saracut and Ruxandra Avram

for the Nokia 3310 display driven by Adafruit’s

PCD8544 library. Developped in Arduino version 1.5.2 */


#include

#include

#include


Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);


boolean alive;

//becomes false when the chip touches a tube or the upper/lower margin of the display

int x1,x2,x3,x4,h1,h2,h3,h4,count = 1;

//x1,2… for current horizontal position of each tube

//h1,2… for current vertical position of each tube

//count counts each moment of the game in order to gradually increase difficulty

boolean x1os=true,x2os=false,x3os=false,x4os=false; //true if the coresponding tube is being displayed

//the first tube appears on screen when the game starts

byte dh, dv,score;

//dh – current horizontal distance between any 2 tubes (gradually decreases)

//dv – current vertical distance between any 2 tubes (gradually decreases)


volatile byte v;

//current vertical position of the chip

//decremented in the interrupt routine triggered by the pressed button, incremented once every gameloop execution

//so that the chip falls unless you press the button

#define XCHIP 30 //x position of chip (constant)

#define DHINIT 50 //initial horizontal distance between two tubes

#define DVINIT 35 //initial vertical distance between two tubes

#define DELAY 100 //game speed


//functions that check if the chip hits the tube by comparing coordinates

boolean in1 (int l, int r, int left, int right) {

return ((r>=left)&&(l<= right));

}


boolean in2(int d, int u, int down,int up) {

return ((u<=up)||(d>= down));

}


//returns maximum value of 4 parameters

int maxim (int n1, int n2, int n3, int n4) {

int m;

m = n1;

if (n2>m) m=n2;

if (n3>m) m=n3;

if (n4>m) m=n4;

return m;

}


//bitmaps of the graphic elements


//lower tube contour

static unsigned char PROGMEM tubjos[] = {0xFF,0xF0,


0×80,0×10,


0xDA,0xB0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


};


//solid color lower tube

static unsigned char PROGMEM tubjosplin[] = {0xFF,0xF0,


0xFF,0xF0,


0xFF,0xF0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


};


//upper tube contour

static unsigned char PROGMEM tubsus[] = {0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0×5E,0×20,


0×6D,0xA0,


0×5E,0×60,


0×6D,0×20,


0×5E,0xA0,


0×6D,0×60,


0xDA,0xB0,


0×80,0×10,


0xFF,0xF0,


};


//solid color upper tube

static unsigned char PROGMEM tubsusplin[] = {0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0×7F,0xE0,


0xFF,0xF0,


0xFF,0xF0,


0xFF,0xF0};


//static background

static unsigned char PROGMEM fundal[] = {0×00,0×38,0×00,0×00,0×00,0×00,0×3C,0×00,0×00,0×03,0xC0,


0×03,0xC7,0×80,0×03,0xF0,0×01,0xC3,0×80,0×00,0×04,0×30,


0×04,0×28,0×60,0×04,0×48,0×06,0×10,0×40,0xFC,0×08,0×80,


0×1A,0×81,0×18,0×18,0×04,0×08,0×00,0×33,0×03,0×14,0×20,


0×62,0×00,0×06,0×22,0×8A,0×10,0×00,0×8C,0×08,0xA0,0×80,


0×88,0×0C,0×21,0×48,0×21,0×68,0×91,0×10,0×84,0×48,0×20,


0×92,0×20,0×00,0×80,0×28,0×82,0×01,0×00,0×01,0×42,0×80,


0×00,0×84,0×20,0×42,0×00,0×00,0×24,0×24,0×28,0×00,0×00,


0×08,0×00,0×04,0×80,0×04,0×14,0×80,0×85,0×4A,0×10,0xA0,


0×60,0×21,0×10,0×10,0×81,0×28,0×00,0×11,0×11,0×15,0×00,


0×02,0×2A,0×02,0×15,0×24,0×00,0×29,0×20,0×40,0×42,0×40,


0×00,0×8C,0×80,0×44,0×40,0×85,0×40,0×40,0×04,0×41,0×00,


0×49,0×82,0×24,0×81,0×00,0×10,0×09,0×24,0xC1,0×02,0×20,


0×02,0×04,0×21,0×02,0×09,0×28,0×41,0×04,0×04,0×12,0×00,


0×09,0×22,0×04,0×91,0×00,0×40,0×08,0×03,0×20,0×90,0×20,


0×00,0×20,0×00,0×10,0×21,0×24,0xD0,0×48,0×41,0×0C,0×80,


0×40,0×19,0×20,0×0C,0×80,0×00,0×01,0×05,0×12,0×21,0×00,


0×82,0×42,0×41,0×21,0×08,0×03,0×32,0×90,0×20,0×14,0×40,


0×08,0×28,0×84,0×10,0×50,0×48,0×40,0×08,0×4A,0×42,0×80,


0×94,0×81,0×4A,0×40,0×81,0×04,0×10,0×00,0×00,0×00,0×00,


};


//small chip contour

static unsigned char PROGMEM chip[] = {0×55,0×40,


0xFF,0xE0,


0×80,0×20,


0×80,0×60,


0×80,0×20,


0xFF,0xE0,


0×55,0×40};


//small chip solid colour

static unsigned char PROGMEM chipplin[] = {0xFF,0xE0,


0xFF,0xE0,


0xFF,0xE0,


0xFF,0xE0,


0xFF,0xE0,


0xFF,0xE0,


0xFF,0xE0};


//startup chip

static unsigned char PROGMEM start[] = {0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,


0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×03,0xF0,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×02,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×02,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×02,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×02,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×03,0xF0,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xC0,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×30,


0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,


0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0×63,0×18,0xC6,0×31,0×8C,0×63,0×18,0xC6,0×31,0×8C,0×60,


0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,


};













void setup() {

Serial.begin(9600);

PORTD = B100;

display.begin();

display.setContrast(55);

display.clearDisplay();

display.drawBitmap(0, 0,start, 84, 48, 1);

display.setCursor(6,20);

display.print(“FLAPPY CHIP”);

display.display();

delay(3000);

display.clearDisplay();





}


void loop() {

gameLoop();

finalScore();

}




void gameLoop() {




v = 20;

x1 = 84;

x2 = 0;

x3 = 0;

x4 = 0;

score = 0;

count = 1;

x1os = true;

x2os = false;

x3os = false;

x4os = false;

dh = DHINIT;

dv = DVINIT;

beginning();

while (digitalRead(2) == HIGH) ; //waits for the button to be pressed

alive = true;

attachInterrupt(0, button, FALLING); //attaching the ISR that makes the chip climb when the button is pressed (on the falling edge of digital pin 2)

while (alive) {

randomSeed(analogRead(A1)); //feeding the random number generator a “random” value by reading an unused analog pin

dispChip(); //displays the chip


//checks if the tubes go offscreen

if (x1<-12) {

x1=0;

x1os=false;

}

if (x2<-12) {

x2=0;

x2os=false;

}

if (x3<-12) {

x3=0;

x3os=false;

}

if (x4<-12) {

x4=0;

x4os=false;

}


//reintroduces tubes

if ((x1os == false) && ((84-maxim(x1,x2,x3,x4)) == dh)) {

x1=84;

h1 = random(5,35);

x1os = true;

}

if ((x2os == false) && ((84-maxim(x1,x2,x3,x4)) == dh)) {

x2=84;

h2 = random(5,35);

x2os = true;

}

if ((x3os == false) && ((84-maxim(x1,x2,x3,x4)) == dh)) {

x3=84;

h3 = random(5,35);

x3os = true;

}

if ((x4os == false) && ((84-maxim(x1,x2,x3,x4)) == dh)) {

x4=84;

h4 = random(5,35);

x4os = true;

}


//moves the tubes to the left

if (x1os) x1–;

if (x2os) x2–;

if (x3os) x3–;

if (x4os) x4–;

count++;

dispTube();

display.print(”           “);

display.print(score);

display.display();

//gradually decreases horizontal and vertical distance between tubes

if (count%50 == 0) {

dv = dv-1;

dh= dh-1;

}


//checks if the chip hits the tubes

if (x1os)

if (in1(XCHIP,XCHIP+11,x1,x1+12))

if (in2(v+7,v,h1+dv,h1)) {

dead(v);

alive = false;

}

if (x2os)

if (in1(XCHIP,XCHIP+11,x2,x2+12))

if (in2(v+7,v,h2+dv,h2)) {

dead(v);

alive = false;

}

if (x3os)

if (in1(XCHIP,XCHIP+11,x3,x3+12))

if (in2(v+7,v,h3+dv,h3)) {

dead(v);

alive = false;

}

if (x4os)

if (in1(XCHIP,XCHIP+11,x4,x4+12))

if (in2(v+7,v,h4+dv,h4)) {

dead(v);

alive = false;

}



if (v > 41) alive = false; //checks if the chip hits the lower screen margin

if ((v >=250) && (v <=255)) //checks if the chip hits the upper screen margin

dead(0);


//increments the score as you pass by each tube

if ((x1os && (x1==XCHIP))||(x2os && (x2==XCHIP))||(x3os && (x3==XCHIP))

|| (x4os && (x4==XCHIP))) score++;


v += 1; //makes the chip fall

delay(DELAY);

}

detachInterrupt(0);

}


//ISR that runs each time you press the button

void button ()  {

v -= 4;

delayMicroseconds(5000);



}


//display the chip

void dispChip () {

display.clearDisplay();

display.drawBitmap(0, 33,fundal, 84, 20, 1);

display.drawBitmap(XCHIP, v,chipplin, 11, 7, 0);

display.drawBitmap(XCHIP, v,chip, 11, 7, 1);

}


//display the tubes

void dispTube () {


if (x1os) {

display.drawBitmap(x1, h1+dv,tubjosplin, 12, 32, 0);

display.drawBitmap(x1, h1+dv,tubjos, 12, 32, 1);

display.drawBitmap(x1, -32+h1,tubsusplin, 12, 32, 0);

display.drawBitmap(x1, -32+h1,tubsus, 12, 32, 1);

}

if (x2os) {

display.drawBitmap(x2, h2+dv,tubjosplin, 12, 32, 0);

display.drawBitmap(x2, h2+dv,tubjos, 12, 32, 1);

display.drawBitmap(x2, -32+h2,tubsusplin, 12, 32, 0);

display.drawBitmap(x2, -32+h2,tubsus, 12, 32, 1);

}

if (x3os) {

display.drawBitmap(x3, h3+dv,tubjosplin, 12, 32, 0);

display.drawBitmap(x3, h3+dv,tubjos, 12, 32, 1);

display.drawBitmap(x3, -32+h3,tubsusplin, 12, 32, 0);

display.drawBitmap(x3, -32+h3,tubsus, 12, 32, 1);

}

if (x4os) {

display.drawBitmap(x4, h4+dv,tubjosplin, 12, 32, 0);

display.drawBitmap(x4, h4+dv,tubjos, 12, 32, 1);

display.drawBitmap(x4, -32+h4,tubsusplin, 12, 32, 0);

display.drawBitmap(x4, -32+h4,tubsus, 12, 32, 1);

}

}


//makes the chip fall

void dead (byte vi) {

for (v=vi; v<41; v++) {

dispChip();

dispTube();

display.print(”           “);

display.print(score);

display.display();

delay(20);

}

}


//game startup

void beginning () {

display.clearDisplay();

display.drawBitmap(0, 33,fundal, 84, 20, 1);

display.drawBitmap(30, v,chip, 11, 7, 1);

display.print(“Press to start”);

display.display();

}


//searches highscore in EEPROM

byte getHighScore() {

int i = 0;

byte hs = 0;

boolean found = false;

while ((i<1022) && (!found)) {

if (EEPROM.read(i) == ‘H’)

if (EEPROM.read(i+1) == ‘S’) {

hs = EEPROM.read(i+2);

found = true;

}

i++;

}

return hs;

}


//sets new highscore in EEPROM

void setHighScore (byte hs) {

int i = 0, j=0;

boolean found = false;

while ((i<1022) && (!found)) {

if (EEPROM.read(i) == ‘H’)

if (EEPROM.read(i+1) == ‘S’) {

EEPROM.write(i,0xFF);

j = i+2;

found = true;

}

i++;

}

EEPROM.write(j,’H');

EEPROM.write(j+1,’S');

EEPROM.write(j+2,hs);


}


//displays score at the end

void finalScore() {

display.clearDisplay();

display.drawBitmap(0, 0,start, 84, 48, 1);

if (score <= getHighScore()) {

display.setCursor(4,10);

display.print(“Your score:”);

display.print(score);

display.setCursor(6,30);

display.print(“Highscore:”);

display.print(getHighScore());

display.display();

}

else

{

display.setCursor(4,10);

display.print(“New Highscore”);

display.setCursor(37,22);

display.print(score);

display.display();

setHighScore(score);

}

//do nothing until the button is pressed

while (digitalRead(2) == HIGH) ;


}



Autor :  Saracut Stelian

Sursa :  saracut.ro

citeste mai departe

Ceas cu alarma cu Arduino

Autor - adi_clepcea -25/05/2014-

M-a intrebat o cunostinta daca pot sa ii fac “ceva care sa porneasca un motor cand este programat, dar sa o faca repetitiv si diferit pe anumite zile” (de fapt este vorba de niste clopote de la o biserica, dar modulul final are multe alte posibile utilizari).

M-am gandit si am ajuns la concluzia ca este posibil si interesant, asa ca, am facut doua shielduri. Unul este un ceas de timp real cu DS1307 si unul este un shield cu trei relee care sa porneasca trei motoare la un anumit interval. Aceste shielduri puse peste arduino si legate la un LCD de 16×2 imi arata ora curenta, ziua saptamanii si data (pe care pot sa le schimb cum consider eu de cuviinta). De asemenea se pot seta pana la 5 alarme (de fapt s-ar putea pana la 9, dar nu am vazut rostul atator alarme). Fiecare alarma poate sa ruleze in zilele saptamanii pe care le doreste utilizatorul.

De exemplu, vreau un ca sistemul de udat gazonul sa imi porneasca luni, mirecuri si vineri la ora 7 dimineata si la 8 seara, iar sambata si duminica sa imi porneasca doar la 7 dimineata pentru ca sunt acasa si nu vreau sa ma ude daca am chef sa stau pe gazon seara. In cazul asta, setez o alarma la ora 7 dimineata si una la 8 seara. Setez la alarma de la ora 7 dimineata sa porneasca luni, miercuri, vineri, sambata si duminica, iar la cea de la ora 8, sa porneasca doar luni, miercuri si vineri. Simplu.

Acum… shieldurile.

1. Ceasul de timp real (DS1307).

In ce priveste ceasul de timp real, se poate folosi un modul de la Robofun, dar eu nu am gasit un shield la ei si vream sa stea tot montajul frumos intr-o cutie la final, asa ca mi-am facut un shield cu un DS1307 pe el.

DS1307 este un integrat de la Maxim care stie sa tina evidenta trecerii timpului cu o eroare foarte mica. Ceea ce m-a determinat sa il folosesc (in loc sa fac un ceas pe arduino) a fost faptul ca DS1307 poate folosi o baterie (precum cea de pe placa de baza a unui calculator de ex.) si nu va pierde evidenta timpului nici daca se intrerupe alimentarea shieldului. Asta ma scapa de corvoada resetarii ceasului de fiecare data cand se ia curentul.

Fiind un modul care tine evidenta timpului si cum este practic sa si vezi cat este ora daca tot folosesti un astfel de modul, am prevazut si o rezistenta reglabila pe el (pentru un LCD) si, desigur, fiindca este pus peste arduino, am pus si un buton de reset ca sa poate fi restartat arduino la nevoie.

Mai jos se poate vedea cum arata shieldul (placa PCB) in Eagle.

Shield DS1307

2. Shieldul cu relee

As fi putut folosi un shield de la Robofun (si probabil ca voi puteti folosi acest shield), dar cum aveam la indemana trei relee (JV-5S-KT) activate la 5V, am decis sa le folosesc pe acelea.

Nu mi-a iesit atat de frumos ca cel de la Robofun ce-i drept, si am fost nevoit sa recurg la doua, trei sarmulite (ok … mai multe) pentru a realiza toate conexiunile, fiindca am folosit PCB one sided, dar … am reusit.

Asadar, asa arata shieldul cu trei relee.

Shield 3 Relee

In aceasta imagine se poate vedea un sir de pini (in dreapta sus). Acest sir de pini l-am folosit pentru a lega LCD-ul si trei butoane.

Firele de la LCD se leaga pe pinii din stanga, iar ultimii trei pini din dreapta sunt pentru butoane. Un buton pentru a intra in meniu si doua pentru a naviga.

Se pot vedea rutele neconectate (la care am folosit sarmulite :) ).

3. Codul

Librariile folosite sunt:

#include “Wire.h”
#include “LiquidCrystal.h”
#include “math.h”
#include “EEPROM.h”

Wire este folosita pentru comunicarea cu DS1307 (I2C).

LiquidCrystal este folosita pentru LCD 16×2.

Math este folosita pentru lucruri destepte in cod.

EEPROM este folosita pentru a salva alarmele in EEPROM, ca sa nu ne pacaleasca cei de la Enel si sa ramanem cu gazonul neudat  :) .

Pentru cei interesati, in final, am ajuns sa am un Arduino peste care am doua shielduri: unul de timp real si unul cu relee. De asemenea mai am legat si un LCD la shieldul cu relee si 3 butoane, cu ajutorul carora reusesc sa schimb ora, data, ziua saptamanii si sa setez alarmele.

Codul ocupa cam jumatate din cei 32 kb ai Arduino, deci nu este prea mare.

Atasate sunt si schitele Eagle.

Sper sa pun si niste imagini cu modulul cat de curand.

Zip  cu fisierele eagle. clopote

Zip cu codul arduino: clopoteArduino

citeste mai departe

RaspFM – Player-ul tau de masina

Autor - Edward -07/02/2014-

Player – FM dedicat pentru masina ta . E mic , usor de folosit si nu foarte scump de confectionat !

Sursele si imaginea acestui proiect o gasiti pe SourceForge

A fost deja publicata o imagine a proiectului dar are o mica problema la conectarea cu bluethooth.

Pentru a putea face acest proiect aveti nevoie de :

1. Raspberry pi

2. Un card de minim 8 GB / systemul ocupa 2 gb restul sunt pentru muzica.

3. Un adaptor bluethooth / pentru conectarea cu telefonul ( Compatibil LINUX ) .

4. (Optional ) Un modem 3g impreuna cu un abonament de net / preferabil orange pentru romania deoarece merge foarte bine !  ( Compatibil LINUX )

5. (Optional) Display LCD 20×4 ( atentie nu se descurca foarte bine cu functiona stereo activata din cauza encoderului audio. / Lipsa resurse.

Cam atat pentru partea hardware .

Soft-ul il puteti descarca de pe SourceForge , link-ul este mai sus. Este o distributie bazata pe Raspbian , fara interfata grafica , totul se controleaza folosind o interfata web accesibila prin bluethooth sau lan.

Ip-ul de bluethooth este 192.168.3.1

Ip-ul pe lan il primeste de la un router sau orice alt dhcp server

User pi

pass 1234

Prima varianta a fost-ului are cateva bug-uri pentru persoanele care nu au cunostinte de programare va rugam sa nu o incercati . In cursul zilei pe site va aparea o varianta din 7.02.2014 deci aceasta este o varianta functionala .

Daca intampinati probleme in folosire va rog nu ezitati sa ma contactati.


Functionalitate :

Player radio de pe internet .

Music Player – Muzica de pe stick sau card.

Youtube – Player online – necesita internet bunicel , posibile mici probleme cu functia stereo / Posibilitate de download melodii pe sd card / pe timpul download-ului nu incercati sa dati play la nici o melodie.

Astea sunt functiile pe care la puteti gasi in momentul de fata in acest proiect .

citeste mai departe

Senzor de greutate

Autor - adi_clepcea -06/01/2014-

De cand am vazut senzorul de greutate de pe site-ul www.robofun.ro, am vrut sa il folosesc.  Problema era ca in tutorialul de la pe site-ul www.nerdkits.com senzorul de greutate avea 4 fire, iar cel de pe site-ul robofun … are doar 3 fire.

Nu am inceput decat de vreo un an, doi sa mai cochetez cu electronica, asa ca nu imi era clar de unde sa incep. Am inceput sa caut pe internet si … incet, incet am reusit sa gasesc solutia. M-am gandit ca poate o sa foloseasca si altora si de accea m-am hotarat sa scriu articolul asta. Sa trecem la treaba.

In primul rand am descoperit cum functioneaza senzorul asta. Se pare ca lamela pe care se va aplica forta (greutea) este formata din doua metale diferite. Cand se aplica o forta pe lamela, aceasta se indoaie imperceptibil. Metalul de dedesubt se va comprima, iar cel de deasupra se va alungi. Normal ca asta va duce la o modificare corespunzatoare a rezistentei. Problema este ca modificarea rezistentei este foarte mica. Ea nu poate fi masurata cu un aparat de masura (am auzit ca se poate daca ai aparat un profesional sensibil, dar al meu nu este chiar asa de destept :) ), asadar arduino sau orice alt microcontroler nu are nici o sansa sa vada diferenta.

Am descoperit ca un tip destept, pe numele lui Wheatstone a descoperit ca poti face o punte de rezistente si sa o folosesti pentru a amplifica chiar si o mica schimbare de valoare la oricare din cele 4 rezistente ce compun puntea.

Senzorul nostru are trei fire, unul este gnd (firul albastru), unul este vcc (firul rosu) si unul este iesirea de la senzor (firul alb). Firul alb este legat in senzor la vcc printr-o rezistenta de 1KOhm (am masurat eu cu aparatul meu nu prea destept si am ajuns la aceasta concluzie :) ). Asadar avem o rezistenta si mai avem nevoie de inca 3.  Vom lua 3 rezistente de 1KOhm si vom crea impreuna cu rezistenta interna a senzorului o punte Wheatstone.

Odata puse in puntea Wheatstone am ajuns la concluzia ca cei de la nerdkits aveau dreptate ca tot nu se poate inca citi nici o valoare cu un aparat de masura obisnuit. Asa ca am luat si eu un amplificator operational, atata doar ca eu aveam din intamplare un LM358 si nu modelul celor de la nerdkits. Zic din intamplare pentru ca habar nu aveam cum functioneaza un amplificator (nu zic eu ca acum sunt expert, dar am vazut cum pot sa il folosesc pe al meu pentru a-mi masura valorile senzorului).

Montajul folosit este unul denumit Bridge Current Amplifier ( in specificatiile lui LM358 se poate vedea la pagina 20). Am mai folosit si Non-inverting DC Gain Output, dar am ramas pana la urma la primul montaj (parea destinat :) ).

Schema

Conform specificatiilor LM358, cu cat sunt mai mari R4 si R5, cu atat va creste amplificarea, asadar vom vedea diferente mai mari la aplicarea unor forte egale la voltajul de la iesire.

Am atasat si o diagrama Fritzing:

Fritzing

Rezistentele R1, R2 si R3 sunt de 1k pentru ca fac parte din puntea Wheatstone dupa cum am precizat anterior.

Tensiunea de iesire poate fi masurata cu Arduino sau AVR sau orice alt microcontroller care are intrari analogice.

Am facut si un mic montaj pentru testare. Atasat se gaseste si codul pentru arduino si codul Processing pentru testare. Codul processing afiseaza un cerc alb pe fond negru care creste si scade odata cu greutatea simtita de senzor.

Senzor de greutate -  cod

Citirile nu sunt foarte exacte, dar asta este probabil normal tinand cont de amplificarea de la mijloc si de montaj care este facut pe o placa de prototipare, dar daca iau in considerare pasi de 50 atunci montajul functioneaza chiar bine. Citirea facuta fara nici o sarcina este in jur de 300 (pentru o valoare maxima de 1024 la analogul arduino). Nu stiu exact de ce, dar tensiunea scoasa de montaj cand nu este nici o sarcina nu este 0. Dupa cum spuneam nu am multa experienta, dar si asa, montajul se poate folosi.

Bafta

citeste mai departe

Tmiya Tracked Robot(Kit robot cu senile)

Autor - adrian -12/12/2013-


Salutare In micul meu tutorial de astazi va voi invata cum sa faceti un robot controlat prin bluetooth de pe un telefon cu android.

Materiale:

Kitul Robotului care il gasiti la ROBOFUN:http://www.robofun.ro/kit-roboti/kit-robot-senile-arduino-driver-bluetooth

4 Distantiere:http://www.robofun.ro/mecanice/suruburi-piulite-conectare/distantier-alama-10mm-m3-surub–m3-piulita

1 sasiu din policarbonat transparent sau orice alt material doriti

2 Acumulatoare Li-po Kingmax

4 suruburi si 4 piulite M3

in prima parte trebuie sa asamblati kitul robotului si taiati sasiul de sus dimensiunile sunt l=11 si L=18(11X18)

In a 2a parte urmeaza electronica

1.Infigeti L298 peste Arduino UNO

ATENTIE!!!!

cand veti alimenta robotul este necesar ca arduino sa fie alimentat de primul acumulator iar L298 sa fiealimentat din celalat acumulator

Bluetooth Mate Se conecteaza la L298 astfel

GND->GND(L298)

VIN->5V

TX->RX(L298) RX este marcat pe driver cu 0

RX->TX(L298) iar TX este marcat cu cifra 1

CTS-1->RTS-o(Ambele sunt de pe bluetooth mate)

montati toata partea electronica pe sasiu

Urmeaza sa incarcati codul pe arduino:

1.Este pentru cei care vor sa il controleze din aplicatie:


nt MOTOR1_PIN1 = 3;
int MOTOR1_PIN2 = 5;
int MOTOR2_PIN1 = 6;
int MOTOR2_PIN2 = 9;
#define DEBUG true
#define STX 0×02  // Necesar pentru soft
#define ETX 0×03  // Necesar pentru soft
int i=0;
byte cmd[5] = {0, 0, 0, 0,0}; // Aici se stocheaza valorle primite prin Bluetooth
int x,y, A,B;
void stopIfFault(); // Motor
void setup() {
Serial.begin(9600); // adjust to your Bluetooth card
Serial.println(“Johny Five”);
}
void loop() {
if(Serial.available()) { // received from smartphone
delay(5);
cmd[0] = Serial.read();
if(DEBUG) Serial.println(cmd[0]); // to serial monitor
if(cmd[0] == STX) {
i=1;
while(Serial.available() && ((cmd[i]=Serial.read()) != ETX)) {
if(i>4) break;
if(DEBUG) {Serial.print(i); Serial.print(“: “); Serial.println(cmd[i]);}
i++;
}
}
// Cei 4 biti cititi sunt valori de voltaje, nu coordonate
if (cmd[1]==0)
x=cmd[2]-200;
else if (cmd[1]==1)
x=cmd[2]-72;
else if (cmd[1]==2)
x=cmd[2]+56;
if (cmd[3]==0)
y=cmd[4]-200;
else if (cmd[3]==1)
y=cmd[4]-72;
else if (cmd[3]==2)
y=cmd[4]+56;
// pana aici am calculat valorile X,Y ale coordantelor joystick-ului
Serial.print(“X: “); Serial.println(x);
Serial.print(“Y: “); Serial.println(y);
if (y>0)
{
if (x>0)
{
A=y;
B=y-x;
}
else
{
A=x+y;
B=y;
}
}
else
{
if (x>0)
{
A=y;
B=x+y;
}
else
{
A=y-x;
B=y;
}
}
// cu un algoritm matematic propriu am calculat valorile A si B pe care le trimit motoarelor pentru a functiona cum planuisem
go (A*4, B*4);
Serial.print(“A: “); Serial.println(A);
Serial.print(“B: “); Serial.println(B);
}
delay(5);
}
void go(int speedLeft, int speedRight) {
if (speedLeft > 0) {
analogWrite(MOTOR1_PIN1, speedLeft);
analogWrite(MOTOR1_PIN2, 0);
}
else {
analogWrite(MOTOR1_PIN1, 0);
analogWrite(MOTOR1_PIN2, -speedLeft);
}
if (speedRight > 0) {
analogWrite(MOTOR2_PIN1, speedRight);
analogWrite(MOTOR2_PIN2, 0);
}
else {
analogWrite(MOTOR2_PIN1, 0);
analogWrite(MOTOR2_PIN2, -speedRight);
}
}

nt MOTOR1_PIN1 = 3;int MOTOR1_PIN2 = 5;int MOTOR2_PIN1 = 6;int MOTOR2_PIN2 = 9;
#define DEBUG true  #define STX 0×02  // Necesar pentru soft#define ETX 0×03  // Necesar pentru soft
int i=0;byte cmd[5] = {0, 0, 0, 0,0}; // Aici se stocheaza valorle primite prin Bluetoothint x,y, A,B;

void stopIfFault(); // Motor

void setup() {    Serial.begin(9600); // adjust to your Bluetooth card
Serial.println(“Johny Five”);
}
void loop() {  if(Serial.available()) { // received from smartphone    delay(5);    cmd[0] = Serial.read();    if(DEBUG) Serial.println(cmd[0]); // to serial monitor    if(cmd[0] == STX) {      i=1;      while(Serial.available() && ((cmd[i]=Serial.read()) != ETX)) {        if(i>4) break;        if(DEBUG) {Serial.print(i); Serial.print(“: “); Serial.println(cmd[i]);}        i++;      }    }// Cei 4 biti cititi sunt valori de voltaje, nu coordonate    if (cmd[1]==0)    x=cmd[2]-200;    else if (cmd[1]==1)     x=cmd[2]-72;    else if (cmd[1]==2)    x=cmd[2]+56;      if (cmd[3]==0)    y=cmd[4]-200;    else if (cmd[3]==1)    y=cmd[4]-72;    else if (cmd[3]==2)    y=cmd[4]+56; // pana aici am calculat valorile X,Y ale coordantelor joystick-ului     Serial.print(“X: “); Serial.println(x);    Serial.print(“Y: “); Serial.println(y);      if (y>0)    {      if (x>0)       {        A=y;        B=y-x;       }    else      {        A=x+y;        B=y;      }      }      else      {        if (x>0)          {            A=y;            B=x+y;          }        else          {            A=y-x;            B=y;          }      }   // cu un algoritm matematic propriu am calculat valorile A si B pe care le trimit motoarelor pentru a functiona cum planuisem     go (A*4, B*4);      Serial.print(“A: “); Serial.println(A);    Serial.print(“B: “); Serial.println(B);
}  delay(5);}
void go(int speedLeft, int speedRight) {  if (speedLeft > 0) {    analogWrite(MOTOR1_PIN1, speedLeft);    analogWrite(MOTOR1_PIN2, 0);  }   else {    analogWrite(MOTOR1_PIN1, 0);    analogWrite(MOTOR1_PIN2, -speedLeft);  }   if (speedRight > 0) {    analogWrite(MOTOR2_PIN1, speedRight);    analogWrite(MOTOR2_PIN2, 0);  }   else {    analogWrite(MOTOR2_PIN1, 0);    analogWrite(MOTOR2_PIN2, -speedRight);  }}

2.Este pentru cei care vor sa ii puna leduri robotului in fata si in spate(sau doar in fata) daca aveti de exemplu 4 leduri puteti modifica in cod sa fie pinii 10,11,12 si 13(eu mi-am pus doar 10 si 11 deoarece am cate doua circuite care functioneaza ca 1 singur adica este legat unu de altu iar din al doilea ies doar 2 fire care aprind 2 circuite,la fel si in spate) cand robotul merge in fata se vor aprinde cele din fata,cand merge in spate se vor aprinde cele din spate:

int MOTOR1_PIN1 = 3;

int MOTOR1_PIN2 = 5;

int MOTOR2_PIN1 = 6;

int MOTOR2_PIN2 = 9;


#define DEBUG true

#define STX 0×02  // Necesar pentru soft

#define ETX 0×03  // Necesar pentru soft


int i=0;

byte cmd[5] = {0, 0, 0, 0,0}; // Aici se stocheaza valorle primite prin Bluetooth

int x,y, A,B;





void stopIfFault(); // Motor



void setup() {


Serial.begin(9600); // adjust to your Bluetooth card


Serial.println(“Johny Five”);

pinMode(10,OUTPUT);

pinMode(11,OUTPUT);


}


void loop() {

if(Serial.available()) { // received from smartphone

delay(5);

cmd[0] = Serial.read();

if(DEBUG) Serial.println(cmd[0]); // to serial monitor

if(cmd[0] == STX) {

i=1;

while(Serial.available() && ((cmd[i]=Serial.read()) != ETX)) {

if(i>4) break;

if(DEBUG) {Serial.print(i); Serial.print(“: “); Serial.println(cmd[i]);}

i++;

}

}

// Cei 4 biti cititi sunt valori de voltaje, nu coordonate

if (cmd[1]==0)

x=cmd[2]-200;

else if (cmd[1]==1)

x=cmd[2]-72;

else if (cmd[1]==2)

x=cmd[2]+56;


if (cmd[3]==0)

y=cmd[4]-200;

else if (cmd[3]==1)

y=cmd[4]-72;

else if (cmd[3]==2)

y=cmd[4]+56;

// pana aici am calculat valorile X,Y ale coordantelor joystick-ului

Serial.print(“X: “); Serial.println(x);

Serial.print(“Y: “); Serial.println(y);


if (y>0)

{

if (x>0)

{

A=y;

B=y-x;

}

else

{

A=x+y;

B=y;

}

}


else

{

if (x>0)

{

A=y;

B=x+y;

}

else

{

A=y-x;

B=y;

}

}

// cu un algoritm matematic propriu am calculat valorile A si B pe care le trimit motoarelor pentru a functiona cum planuisem


Serial.print(“A: “); Serial.println(A);

Serial.print(“B: “); Serial.println(B);



// AICI PORNIM MOTOARELE SI APRINDEM SI BECURILE


if (A>0 && B>0)

{

digitalWrite(11, LOW);

digitalWrite(10, HIGH);

}


else if (A<0 && B<0)

{

digitalWrite(10, LOW);

digitalWrite(11, HIGH);

}


go (A*4, B*4);



}

delay(5);

}


void go(int speedLeft, int speedRight) {

if (speedLeft > 0) {

analogWrite(MOTOR1_PIN1, speedLeft);

analogWrite(MOTOR1_PIN2, 0);

}

else {

analogWrite(MOTOR1_PIN1, 0);

analogWrite(MOTOR1_PIN2, -speedLeft);

}


if (speedRight > 0) {

analogWrite(MOTOR2_PIN1, speedRight);

analogWrite(MOTOR2_PIN2, 0);

}

else {

analogWrite(MOTOR2_PIN1, 0);

analogWrite(MOTOR2_PIN2, -speedRight);

}

}

aplicatia o gasiti in google play: https://play.google.com/store/apps/details?id=org.projectproto.btjoystick



citeste mai departe

MazeBot – Rezolva orice labirint fara bucle inchise

Autor - lucian.tarida -16/03/2013-

Salut,

Revin, dupa aproape 1 an jumate de la ultimul meu articol pe tehnorama, cu proiectul meu de dizertatie.

Dupa ce mi-am ales tema lucrarii (Proiectarea si realizarea unui sistem de conducere a unui robot mobil printr-un labirint), am hotarat impreuna cu coordonatorul lucrarii sa nu mai fac alt robot, cu toate ca acum este foarte simplu cand ai totul la dispozitie pe www.robofun.ro, si sa-l folosesc tot pe ROBOTL (http://www.tehnorama.ro/robotl) care a mai imbatranit cu 1 an jumate. :)

L-am scos din cutie, l-am sters de praf si m-am apucat sa-i fac unele modificari. Bineinteles ca pentru o rezolutie mai buna la citirea traseului am achizitionat 6 senzori de reflectanta (de linie) si i-am inlocuit pe cei 3 de acelasi tip pe care-i avea ROBOTL.

Din punct de vedere hardware nu au mai fost alte schimbari, exceptand faptul ca am eliminat consumatorii “de efect” (leduri, circuit buzzer) pentru o durata de utilizare mai mare a bateriilor. De asemenea, este important sa subliniez faptul ca am renuntat la bateria de 9V cu care alimentam Arduino pentru ca se consuma exagerat de repede. Am decis sa folosesc 6 baterii de 1,5V pentru o sarcina electrica mai mare. Astfel, MazeBot este cu “un etaj mai sus” decat ROBOTL pentru ca am fost nevoit sa fac spatiu (folosind distantiere) pentru suportul cu cele 6 baterii de 1,5 V. Restul componentelor hardware ale robotului MazeBot le puteti gasi in articolul anterior mentionat, destinat lui ROBOTL.

Partea software se bazeaza pe regula mainii stangi pe perete si un algoritm de optimizare.

In prima etapa, robotul parcurge labirintul conform regulii mana stanga pe perete ce presupune 4 conditii:

1. Daca robotul poate vira stanga , atunci sa vireze stanga.

2. Altfel, daca robotul poate inainta, atunci sa inainteze.

3. Atlfel, daca robotul poate vira dreapta, atunci sa vireze dreapta.

4. Daca robotul este la capat “mort” atunci sa intoarca.

La fiecare decizie, in memoria microcontrollerului se va inregistra o litera corespunzatoare : L, R, S, B (back), D (done) .

In cea de-a doua etapa se parcurge labirintul pe calea optima conform algoritmului de optimizare. Optimizarea inseamna inlocuirea in memoria microcontrollerului a grupurilor formate din 3 litere care contin la mijloc litera B(back) pentru ca asta inseamna ca robotul a facut o intoarcere si a luat-o pe o cale gresita. De exemplu, grupul de litere LBL se va inlocui cu litera S s.a.m.d.

Pentru cei interesati, puteti afla mai multe de aici :

http://www.pololu.com/file/0J195/line-maze-algorithm.pdf http://www.patrickmccabemakes.com/PatrickMccabeMakes/Mazev3.html

Iata rezultatul :

Va multumesc pentru timpul acordat!
Pentru informatii si ajutor in cadrul proiectelor voastre nu ezitati sa ma contactati.
Lucian  (Contact: tarida.lucian@yahoo.com)

citeste mai departe

3D Printers

Autor - TinHead -28/12/2012-

Salutare!

Ei bine m-am potolit cu CNC-ul in apartament (adica asta ), in principal din cauza prafului si a zgomotului infernal, dar si pentru ca tot netul vuia despre asa numitele 3D printers … impropriu spus imprimantele 3D.

In primul rand ce este o imprimanta 3D?

Este o masina de depus material plastic, constituita din 3 axe, sa le spunem X,Y,Z si un mecanism de extrudare pentru filament de plastic numit generic extrudor.
Functioneaza prin topirea materialului plastic si depunerea sa in straturi suprapuse pentru a creea un corp tridimensional.

Acest tip de masinarie exista de ani buni dar preturile sunt imense pentru cele industriale. Prin 2004 insa a aparut proiectul RepRap initiat de prof. Adrian Bowyer de la universitatea din Bath, UK. Proiectul a fost lansat pentru a se creea un 3D printer ieftin, ce isi poate creea propiile componente, in fine cel mai bine vedeti descrierea aici :)

Proiectul a fost un success si au fost fost creeate mai multe modele de imprimante open source ce au fost si sunt in cotinuare imbunatatite.

Probabil cel mai cunoscut model este Prusa Mendel si cu acesta am decis sa incerc si eu.

Cu ajutorul unui membru letsmakerobots.com din USA care detinea deja o astfel de imprimanta, am putut pune mana pe un set de piese printate pentru structura, un set de LM8UU (rulmenti lineari), setul de piese pritate necesare pentru extrudor si asa numitul hotend pentru aproximativ 200 USD.

Cu electronica am scapat usor, avaind deja driverele si motoarele de la CNC a trebuit doar sa fac o placa cu un ATMega644 pentru a putea rula firmware-ul

In continuare am dat iama prin Hornbach dupa tije filetate de 8 mm, suruburi si piulite.
Barele drepte de 8 mm au fost cel mai greu de gasit, la noi se aduc de la 10 mm in sus, norocul a fost ca aveam cateva bucati de prin imprimante vechi. Diametrele nu au fost perfect egale dar au mers.

Ce a iesit in final arata cam asa:

Prusa front
Iar din spate cu electronica homemade:

Prusa

Si primul cub reusit:
cube

Evident cu o astfel de jucarie constructia in sine este doar primul pas, urmatorul fiind gasirea setarilor perfecte pentru printuri de calitate.
Mie mi-a luat cam o luna de setat, resetat pana sa reusesc sa scot piese utilizabile cum ar fi cele de mai jos:
roti

Fiind prima imprimanta, Prusa mea a suferit de mai multe probleme inca de la inceput, de exemplu placa pe care se depune am facut-o la repeazala, din niste bucati de parchet laminat ramas prin camara. Desi la inceput a fost OK dupa trecerea iernii a inceput sa lucreze, odata cu inclazirea si s-a lasat. Daca suprafata de depunere nu este perfect plata, in unele locuri plasticul va prinde in altele nu, si se pierde o gramada de timp si plastic.

In cele din urma am decis ca este timpul sa fac alta imprimanta si am ales sa fac un Hugo. Acest design este complet diferit de cel al Prusa si ocupa mai putin spatiu pentru aceeasi suprafata.

Astfel s-a nascut BumbleBee.

bb

Toate piesele de plastic de pe BB au fost printate pe Prusa. Odata ce am terminat de printat piesele, am canibalizat Prusa pentru rulmentii lineari si barele de otel, RIP Prusa.

De data asta am renuntat la a folosi driverele vechi si am luat drivere Pololu bazate pe A4988, mult mai mici in dimensiuni decat ale mele. Driverele sunt montate pe o placa Gen7 pe care am modificat-o pentru a inlocui conectorii cu terminale pe surub.

Mecanic BB e mai stabila decat Prusa si am obtinut printuri mult mai bune calitativ cu ea.

Roti dintate:
gears

Si senile:
track

Si tancul final:
tank

Software-ul si firmare-ul folosit pentru a controla imprimanta este cel dezvoltat de Repetier pe github aici.

Cu siguranta am uitat cate ceva posturi mai complete gasiti mai jos:

http://letsmakerobots.com/node/29707

http://letsmakerobots.com/node/32879

Si tancul aici:

http://letsmakerobots.com/node/35363

Cam atat :)

Sarbatori fericite !!

citeste mai departe

Alimentare PI cu alimentator de telefon

Autor - Viorel -09/12/2012-

Primit pe mail de la Gabi (thx, man :) ) :


Mi-ati dat tema de casa si dupa cum ma stiu , nu pot avea liniste pana cand nu termin treaba ,prin urmare, deci !
Incarcator auto chinezesc  Xcell pentru Motorola 12-24 V input 5V /500ma output
La input de 7,00 V , in sarcina pe Raspberry , scoate cam 3.9-4,3 V out, stabil , boot decurge ok, server mode cu apache, mysql + script bash de automatizare clima servere. ( fara USB  stick si retea atasate , din lipsa de timp si spatiu)
La input de 6.9 deja nu mai este stabil,se rebooteaza dupa 3 secunde ,si nu este bine
La 7.00 cu stick usb atasat , led-ul de power fluctueaza ca intensitate dar Raspberry ramane stabil ( fara R/W pe stick -lipsa keyboard la indemana in momentul testului).
Consumul raspberry a ajuns la un record de 1,4 W  ceea ce este bine.
Concluzia  : un incarcator de telefon de 16 RON face treaba mai buna decat un stabilizator LM7805 , pragul la care ramane functional este de 7.00V , asta inseamna ca pe robotica din baterii , daca apare un spike de la un motor si bateria cade sub 7.00V Raspberry rebooteaza.
Prin editarea fisierului de clock de la 700 mai jos , este posibil sa functioneze la tensiuni mai joase dar trebuie testat.
Foto trebuiesc prelucrate si vor fi atasate ulterior , aveti acordul meu pentru publicare pe site-ul dvs impreuna cu cele scrise aici.

citeste mai departe

Tutorial telecomanda IR

Autor - gheorghe.gainaru -04/12/2012-

Cu multe multumiri d-lui Gheorghe Gainaru, autorul materialului de mai jos, pentru efortul depus si bunavointa de a da rezultatele mai departe.

Click aici pentru a descarca tutorialul in format PDF.

Viorel

citeste mai departe

Vino sa ii intalnesti pe jucatorii de fotbal robotic!

Autor - Viorel -24/10/2012-

Centrul de Creatie Tehnica pentru Tineret (inventeaza.ro) in colaborare cu Electrical Engineering STudents` European assoCiation Bucuresti (eeStec) organizeaza luni, 29 octombrie 2012 evenimentul de lansare a proiectului “Fotbal Robotic”, care se va derula incepand cu ora 15:00, in Sala Senatului, corp Rectorat, din cadrul Universitatii Politehnice Bucuresti, Splaiul Independentei, nr. 313, sector 6.


Durata evenimentului este de aproximativ 60 de minute, iar acesta va fi structurat in doua sectiuni distincte. In deschiderea evenimentului vor vorbi: Ionut Cotoi, Presedinte al Asociatiei Centrul de Creatie Tehnica pentru Tineret, Radu Manea, Senior Manager al progamului SSM din cadrul Luxoft Romania, un reprezentant din partea Universitatii Politehnice Bucuresti si Rares Curatu, Vice-Presedinte Resurse Umane in cadrul eeStec LC Bucuresti.


Cea de-a doua parte va consta intr-o demonstratie de fotbal robotic, utilizand intregul sistem de joc (roboti, teren, camera video, software comanda wifi).


Robotii urmeaza a fi programati de catre studentii participanti in cadrul celor patru, respectiv patru sedinte de coaching oferite gratuit in cadrul proiectului in perioada 5 – 29 noiembrie 2012.


Organizarea primului campionat de fotbal robotic pentru clasa Mirosot, desfasurat dupa regulamentul Federatiei Internationale de Fotbal Robotic (FIRA) reprezinta un concept educational inedit, adresat studentilor din cadrul universitatilor cu profil tehnic pasionati de electronica, programare si inteligenta artificiala. Acestia se pot inscrie completand formularul online de pe www.fotbalrobotic.ro pana pe data de 2 noiembrie 2012.


Sponsor: Luxoft Romania

Partener academic: Universitatea Politehnica din Bucuresti

Parteneri: Robofun.ro, Gemma Total Advertising, Webefektiv

Parteneri media: Radio Guerrilla, RegieLive, Sapte Seri, PC World, Resboiu, Newsman, Hipo.ro, VideoLink si Hipnotizat de Muzica.

citeste mai departe