Sida 11 av 23

Re: Val av microprocessor, RGB LED styrning

Postat: 5 oktober 2010, 18:00:53
av dragon9226
Hej.
E85, jag har testat dina kod bitar, men inte riktigt lyckats.
Den andra delen såg mycket bra ut och skulle förkorta mitt program avsevärt, men det tycks vara något fel i den.
Det som händer är att alla färger blir vita i stället för den man anger. Alltså borde det vara något fel på undersökningssatsen, som anger att det ska vara en 1 hela tiden, på varje färg.
Då jag inte har sätt en sådan här undersökningssats förut kan jag tyvärr inte säga vad som är fel. Men enligt mig så skulle det kunna fungera, om jag försöker förstå hur det ska fungera.

Den första delen blir mer av en "random" sats för vilken färg som ska sättas, medan en rad visas i taget, skrollande. (Om man flyttar den undersökande delen till olika platser för färger, i stället för att det bara blir rött).

Re: Val av microprocessor, RGB LED styrning

Postat: 5 oktober 2010, 18:12:36
av E85
Jadu.. jag vet inte vad det kan bero på riktigt och orkar inte kolla igenom tidigare inlägg nu.

(red > 0 ? OUTPUT_RED : 0)
betyder
Om (red > 0) blir värdet OUTPUT_RED, annars 0.

Du får nog prova dig fram med lite olika värden osv. Men nu vet du hur den satsen fungerar iallafall.
Du kommer att behöva "scrolla" på det viset senare om du ska visa mer avancerade bilder för du kan inte ha alla rader tända samtidigt då.

edit: Snubblade förmodligen över svaret ändå på sidan 9. Du måste invertera definitionerna som jesse skriver.

Re: Val av microprocessor, RGB LED styrning

Postat: 5 oktober 2010, 19:13:45
av dragon9226
I "vanliga fall" med den funktion jag skrivit så så får jag alla färger på rätt sätt, alltså röd när jag aktiverar röd.
Men när jag använder din så blir det bara vitt (alla färger).
(Jag har inverterat OUTPUT_RED, GREEN och BLUE: #define OUTPUT_BLUE (~(1<<PB3)) o.s.v.)

Re: Val av microprocessor, RGB LED styrning

Postat: 5 oktober 2010, 22:13:37
av jesse
Jag vet nu inte hur hela programmet ser ut, men det är viktigt att du vet vad de olika variablerna egentligen innehåller för data.

ta t.ex. det här exemplet:

Kod: Markera allt

// funktion för att skicka ut en bit på shiftregister
void shifta_en_bit(char colour) {     
    PORTB = STROBE | colour; // sätt färg - "strobe" skall alltid vara på (se * nedan)
    _delay_ms(1);
    PINB = CLOCK; // toggla klockan
    _delay_ms(1);
    PINB = CLOCK;
}
* (En sak att fundera på : Strobe-utgången ska alltid vara ETTA. I koden står det därför PORTB = STROBE | colour;. Men man kan utesluta strobe och skriva PORTB = colour; och strobeutgången blir fortfarande en ETTA. Hur kommer det sig? Strobe definieras som #define STROBE (1<<PB6) )

Här tar funktionen in ett 8-bitars värde (char colour). Vad gör de olika bitarna i den variabeln?
På första raden i funktionen skickar vi ut data på port B.

Så varje bit i "colour" motsvarar en utgång på PORTB. Har man schemat framför sig (sidan7 i denna tråden) ser man att PORTB har en massa olika funktioner : bit 3 är OUTPUT_BLUE, bit 4 är OUTPUT_GREEN och bit 5 är OUTPUT_RED. Bit 6 är strobe. Det är därför jag har definierat färgerna (inverterat) såhär:

Kod: Markera allt

#define OUTPUT_BLUE  ( ~(1<<PB3))
#define OUTPUT_GREEN ( ~(1<<PB4))
#define OUTPUT_RED   ( ~(1<<PB5))
För att få ut GUL färg måste bit 5 och 4 vara nolla, och bit 3 vara etta (och alla övriga bitar kan också var etta) . PORTB = 0b11001111;

(1<<5) är detsamma som 0b00100000. inverterar vi det värdet (~(1<<5)) blir det 0b11011111 som är värdet på OUTPUT_RED. om vi nu skriver:

Kod: Markera allt

shifta_en_bit(OUTPUT_RED & OUTPUT_GREEN);
får vi gul på första kolumnen.

bitvis och (&):

Kod: Markera allt

    0b11011111
&   0b11101111
    ========
    0b11001111
Detta är hur bitarna ser ut på PORTB i det läge man skickar en puls till shiftregistren att läsa in datan.

Men det är ju åtta kolumner som ska ha var sin färg. Och i den här funktionen:

Kod: Markera allt

// funktion som skickar ut data till shiftregistren
// red,blue,green innehåller var och en 8 bitar data.
// varje bit tänder en LED i den kolumnen
void skicka_data(char red, char blue, char green) {
         // SKRIV ALGORITM HÄR
}
så hade jag tänkt att de åtta bitarna i var och en av variablerna red, blue och green kunde motsvara var sin kolumn. På så vis kommer funktionen att kunna sätta alla tänkbara färgkombinationer som finns på 8 kolumner... om den bara kan ta bitarna en och en ur varje färgvariabel och shifta ut dem...
Ett sätt att göra det på kan vara t.ex:

Kod: Markera allt

// funktion som skickar ut data till shiftregistren
// red,blue,green innehåller var och en 8 bitar data.
// varje bit tänder en LED i den kolumnen
void skicka_data(char red, char blue, char green) {
    for (char i=0;i<7;i++) { // åtta varv
      // "output" är den variabel vars databitar kommer att skickas ut på PORTB.
        char output = 0b11111111; // ettställ alla bitar först
      // kolla bit nr 7 i var och en av de tre färgerna
        if (red & 7) output &= OUTPUT_RED;
        if (green & 7) output &= OUTPUT_GREEN;
        if (blue & 7) output &= OUTPUT_BLUE;
      // shifta bitarnas position ett steg år vänster (bit 6 blir bit7 osv..)
        red = (red << 1);
        green = (green << 1);
        blue = (blue << 1);
    // skicka ut data för en kolumn
    // variablen "output" innehåller nu data för alla tre färger
        shifta_en_bit(output); // denna funktion skickar ut datan till shiftregistren
    }
}
Om det är någon operation i den här funktionen du inte förstår så försök sätta dig in i det. Om du ska kunna utveckla projektet behöver du förstå i detalj exakt vad som händer.

Nu kan du med en enda rad skicka ut alla färger på alla kolumner:

Kod: Markera allt

// raden nedan tänder följande färger i ordning kolumn 0 till kolumn7
// svart,röd,blå,grön,gul,violett,vit,magenta,svart
  skicka_data(0b010011100,0b001001110,0b000110110 )// red,blue,green
lägg de tre binära talen över varandra så ser du vilka färger det blir:

Kod: Markera allt

kol   01234567
      ========
red    010011100
blue   001001110
green  000110110
Nu kan man matematiskt eller logiskt skapa olika mönster som man skickar ut med hjälp av den fuktionen. Detta är ett sätt att organisera data på. Här ör de tre kanalerna röd, grön, blå skilda åt. Ett alternativ (som kanske är bättre) är att man har åtta variabler (en för varje rad) i en array, som villserligen är 8-bitars heltal, men där man bara använder tre av bitarna, vilka då motsvarar röd, grön och blå.

char column[8];

Då kan man fortfarande använda de "gamla" färgdefinitionerna om man vill, t.ex.
column[4] = YELLOW;
column[5] = RED;


eller varför inte

Kod: Markera allt

for (char i = 0; i<8; i++) {
    column[i] = i;
}
Du kan ju fundera på hur du skriver en funktion void skicka_data( char* column ) som skickar ut sådan data istället. Fördelen med det är kanske att man sedan kan skapa en matris som innehåller data för alla färger i alla kolumner i alla rader:
char PIXEL[8]∞; // tvådimensionellt!

Re: Val av microprocessor, RGB LED styrning

Postat: 6 oktober 2010, 08:44:07
av dragon9226
ok, nu vet jag vad jag har o göra när jag kommer hem =)

Bara några korta saker:
if (red & 7) output &= OUTPUT_RED;, hur denna fungerar förstod jag inte helt. Är det om den sjunde biten i red är 1 så blir output lika med det den var innan + OUTPUT_RED?

Det där med tvådimensionella fältet skulle nog kunna bli riktigt smidigt. Bara, tänkte du att man ska lagra fyra 8-bitars variabler i varje plats?
Då får man PIXEL[2][6] = 0b10000000(rad), 0b00100000(röd), 0b00010000(grön), 0b00001000(blå);
den första bestämmer vilken rad som ska aktiveras, den andra vilken röd kolumn som aktiveras, den tredje för grön osv.

Fast det där kändes inte helt rätt, men kanske?

De tas emot i skicka_data som om de skickats ut fyra variabler. (Måste dock lägga till en för rader), men sedan är det char red osv.

Re: Val av microprocessor, RGB LED styrning

Postat: 6 oktober 2010, 10:12:56
av jesse
(a)
if (red & 7) output &= OUTPUT_RED;

exakt. den kollat alltså bit 7. eftersom man sen flyttar alla bitar i variabeln ett steg åt vänster så kommer bit 6 att flyttas till bit 7... åtta varv ända till bit 0.

(b)
>tänkte du att man ska lagra fyra 8-bitars variabler i varje plats?
Nej. Varje färg behöver ju bara en bit för att lagras. Tre färger blir tre bitar. Detta får gott och väl plats i en åttabitars variabel. Definitionen av matrisen visar att det är en åttabitars variabel per position: (såg nu att jag själv brutit mot konventionen och använt STORA bokstäver för en variabel. fy! Ändrar genast till små)

char pixel[8]∞; // betyder 8 gånger 8 st 8-bitars heltal.

Vart och ett av dessa heltal kan alltså innehålla information om alla tre färgerna.
Så om röd = bit0, grön= bit1 och blå = bit2 och en ETTA motsvarar "tänd" och NOLLA "släckt" så blir t.ex. pixel[1][1] = 0b001 röd och 0b111 vit.

(Man får försöka lära sig utantill de olika namnen i C på olika variabeltyper. De vanligaste heltalen är: char = 8-bitars heltal, vilket kan anta värden mellan -128 och +127. Används ofta att lagra ASCII-tecken. En textsträng definieras därför som char min_text[] = "Hello World!"; // en array med 13 8-bitars char. Sedan finns det unsigned char (fortfarande 8-bitar, men kan ej hantera negativa tal, kan anta värden mellan 0 och 255), int och unsigned int är de vanligaste heltalen, men är lite luriga då antalet bitar i dem inte är definierade. I AVR-GCC är de 16-bitar, men i andra kompilatorer brukar de vara 32-bitars tal. Ett 16-bitars int kan anta värden mellan -32768 och +32767, unsigned int 0-65535. Sedan finns long , float osv... )

Detta sätt att organisera datan passar alltså INTE ihop med den funktionen jag skrev i förra inlägget (det blir jobbigt att plocka ut de enskilda bitarna när de ska skickas med i funktionsanropet). Jag visar bara olika exempel på hur man kan göra. Sen hur du vill göra får du bestämma själv. (Som sagt, min uppgift är ju inte att skriva det färdiga programmet åt dig, jag bara förklarar principer. Det är du som sedan med hjälp av den kunskapen ska kunna snickra ihop ett program!)

Re: Val av microprocessor, RGB LED styrning

Postat: 10 oktober 2010, 14:14:57
av dragon9226
Hej. Jag har försökt att följa Jesse:s exempel och kommit fram till det nedanstående programmet, jag lyckas inte få riktigt kontroll över färgerna.
Jag kan välja mellan röd grön och blå, och blanda dessa, men bara på hela plattan, alltså blir det inget bra om jag sätter röd till 0b00001111 i skicka_data(); anropet.
Jag har gjort några små justeringar(markerade med *) men inte kommit fram till ett helt fungerande program.
//---------------- standardbibliotek ------------------
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <util/delay_basic.h>

/* definiera pinnar på processorn .
* (1<< BIT) tilldelar VÄRDET av en bit.
* T.ex BIT=5 ger värdet 32. */

// färger
#define OUTPUT_BLUE (~(1<<PB3))
#define OUTPUT_GREEN (~(1<<PB4))
#define OUTPUT_RED (~(1<<PB5))
// shiftregister - styr lysdiodernas färger i kolumner
#define CLOCK (1<<PB2) // shiftregister klocka (SCK)
#define STROBE (1<<PB6) // shiftregister strobe (STR)
// lysdioder - rader
#define RAD0 (1<<PA0) // motsvarar pinne PA0 - dvs LED0 i schemat.
#define RAD1 (1<<PA1)
#define RAD2 (1<<PA2)
#define RAD3 (1<<PA3)
#define RAD4 (1<<PA4)
#define RAD5 (1<<PA5)
#define RAD6 (1<<PA6)
#define RAD7 (1<<PA7) // motsvarar pinne PA7 - dvs LED7 i schemat.

// funktion som skickar ut data till shiftregistren
// red,blue,green innehåller var och en 8 bitar data.
// varje bit tänder en LED i den kolumnen
void skicka_data(char red, char green, char blue) { // SKRIV ALGORITM HÄR (* bytt ordningen ordningen på variablerna, till RGB)


for (char i=0;i<8;i++) { // åtta varv (* en åtta i stället för en sjua, så det blir 8 varv?)
// "output" är den variabel vars databitar kommer att skickas ut på PORTB.
char output = 0b11111111; // ettställ alla bitar först
// kolla bit nr 7 i var och en av de tre färgerna
if (red & 7) output &= OUTPUT_RED;
if (green & 7) output &= OUTPUT_GREEN;
if (blue & 7) output &= OUTPUT_BLUE;
// shifta bitarnas position ett steg år vänster (bit 6 blir bit7 osv..)
red = (red << 1);
green = (green << 1);
blue = (blue << 1);
// skicka ut data för en kolumn
// variablen "output" innehåller nu data för alla tre färger
PORTB = STROBE | output; // denna funktion skickar ut datan till shiftregistren (* här hade du shifta_en_bit(output); vilket jag inte visste riktigt vad jag skulle med, så ändrade till detta.)
}


}

/**** huvudprogrammet ****/
int main(void) {

// initiering av portar (se kapitel 12 i databladet - särskilt 12.2.1)
DDRA = 0b11111111; // alla pinnar på port A ska vara utgångar
DDRB = 0b11111111; // alla pinnar på port B ska vara utgångar


PORTA = 0b11111111; //aktiverar alla rader

while(1) { // ...loopa för evigt...
// raden nedan tänder följande färger i ordning kolumn 0 till kolumn7
// svart,röd,blå,grön,gul,violett,vit,magenta,svart
skicka_data(0b00000000, 0b11111111, 0b00000000 );// red, green, blue
}
}
Vad tror ni?

Det kanske är bra att lyckas med detta innan man börjar med fält.

Re: Val av microprocessor, RGB LED styrning

Postat: 11 oktober 2010, 17:27:21
av jesse
Kollade snabbt och hittade ett fel som säkert är orsaken till det mesta...

Kod: Markera allt

if (red & 7) output &= OUTPUT_RED;
den ska ju kolla bit7, men nu gör den (red & 7) vilket är detsamma som att den kollar bit0,1 och 2! 7 = 0b00000111. Givetvis ska det vara

Kod: Markera allt

if (red & (1<<7)) output &= OUTPUT_RED;
Eftersom (1<<7) är en etta shiftad 7 gånger åt vänster blir det binärt 0x10000000 - det är den biten vi vill kolla!

Hinner inte kolla mer just nu, men testa det först.

Kod: Markera allt

(* en åtta i stället för en sjua, så det blir 8 varv?)
Jovissta ja, såklart :oops:

Re: Val av microprocessor, RGB LED styrning

Postat: 11 oktober 2010, 21:25:26
av dragon9226
Titt!
Där satt det rackarns lilla felet.
Nu fungerar det klockrent.
Jag kan tända enskilda led:s och byta färger fram och tillbaka :)
Tack så otroligt mycket Jesse, och alla andra!

Nu ska jag testa om det går att göra mer komplicerade mönster.
Om någon har något direkt tipps om detta, så skriv gärna en kort kommentar.

(Tillägg)
Nu har jag provat lite enkla mönster, och det fungerar utmärkt =)
Det blir inte ens något flimmer, som det blev tidigare.

PS.
Nu är det bara dimningen kvar, om någon har lust att förklara hu detta kan gå till, så skriv gärna lite granna.
En tanke är att bara tända led:sen en kort stund med en for sats (loop sats), och också ha en liten extra paus i den, så att led:sen inte lyser hela tiden. Är detta ett bra sätt eller finns det något bättre?
(TILLÄGG) Eller blir det bara flimmer av pausen?

Kom tyvärr på detta när jag plockat ihop far dagen...

Re: Val av microprocessor, RGB LED styrning

Postat: 11 oktober 2010, 22:08:00
av jesse
:bravo:

Re: Val av microprocessor, RGB LED styrning

Postat: 12 oktober 2010, 14:05:04
av jesse
När får vi se en video? :P

Re: Val av microprocessor, RGB LED styrning

Postat: 12 oktober 2010, 14:46:33
av dragon9226
Av den färdiga produkten (WUL), eller av min testrigg? som jag lånat, av Swech.

Re: Val av microprocessor, RGB LED styrning

Postat: 12 oktober 2010, 16:00:35
av jesse
Gärna både och!
Kul att se hur det ser ut när du fått det att visa olika mönster. Har du rörliga mönster också?

Re: Val av microprocessor, RGB LED styrning

Postat: 12 oktober 2010, 16:18:18
av dragon9226
Jag har inte hunnit programmera något komplicerat ännu.
Bara två bokstäver. Men något rörligt mönster borde ju gå att knåpa ihop.

Re: Val av microprocessor, RGB LED styrning

Postat: 12 oktober 2010, 17:11:55
av dragon9226
(Jag håller på och knopar ihop en liten visning.
Men plötsligt börjar programmet klaga på att det inte finns plats. (The content of the HEX file does not fit in the selected device).
Detta trotts att jag skrev mindre kod än tidigare och dessutom sedan bytta tillbaka för att testa...
Då trodde jag att de gamla filerna satt på den också, så jag tryckte på erase, men det går fortfarande inte....

Program: 4230 bytes (103.3% Full)
(.text + .data + .bootloader)

Data: 264 bytes (103.1% Full)
(.data + .bss + .noinit)


Så står det i build fönstret....

Vad ska jag göra?)

(TILLÄGG)
Lyckades bli av med en del av problemet.
Men när jag försöker dimma, genom att i en for sats (loop sats), tänder och släcker vissa leds, och i denna ha en paus, som tar for-satsens variabel som sin.
För att få en ökande ljuseffekt. SÅ tycker den att det tar för mycket minne.
Trots att jag bara tar ett litet värde...
Vad är felet?

for (int y = 10; y < 20; y++){
PORTA = 0b00111100;
skicka_data(0b00000000, 0b00000000, 0b00111100 );// red, green, blue
_delay_ms(1);

PORTA = 0b00000000;
_delay_ms(y);
}