Software PWM mit Binärer Zahlenausgabe (RPi)

einhuman197

Grünschnabel
Guten Tag zusammen.
Ich versuche gerade ein C Programm zu programmieren, was mir die Zahlen 1-1000 über die Gertboard LED's in reihe ausgibt. Das funktioniert auch Prima. Nur die Aufgabe lautet dass ich mithilfe von Software PWM (also praktisch dem schnellem Pulsieren von der LED sodass es dunkler für das auge aussieht) die LED dunkler machen soll. Ich hab keine Ahnung wie ich das in den code implementieren soll (ein testcode für eine led hab ich geschrieben und der funktioniert gut) und wäre für jede Hilfe dankbar.

Hier mein funktionstüchtiger code (die pins sind wegem dem Gertboard zwar auf den gpio pins nicht in reihe auf dem board aber schon.
C:
#include <stdio.h>
#include <wiringPi.h>

int zahl[10]={0,0,0,0,0,0,0,0,0,0};
   void binaer (int wert)
{
   for (int i=0; i<10; i++)
   {
       zahl[i]=wert%2;
       wert=wert/2;
   }
}


int main(void)
{
int pins[13] = {6,5,4,3,29,2,1,0,16,15,11,7,9};
int p;
int i;
int j;
wiringPiSetup() ;
for(p=0; p<10; p++)
{
   pinMode (pins[p], OUTPUT);
   digitalWrite (pins[p], LOW);
}

   for(i=0; i<=1000; i++)
   {
       binaer(i);
       for(j=0; j<13; j++)
       {
           digitalWrite(pins[j], zahl[j]);
           delay(10);
       }   
       printf("Zahl: %d \n", i);
   }
   for(p=0; p<13; p++)
   {
       digitalWrite (pins[p], LOW);
   }   
   printf("Aktuelle Zahl: %d \n", i);
}
 

cwriter

Erfahrenes Mitglied
Hi

PWM ist Pulse Width Modulation, und das sollte eigentlich auch schon das meiste sagen.

Du definierst eigentlich 2 Werte:
Einmal die Komplette Kurve, also die Zeit, die eine On-Periode und eine Off-Periode brauchen.
Und als zweites definierst du, wie lange die On-Periode sein soll.

Ein Beispiel:
Wir nehmen 10 Zeiteinheiten als On + Off.
Bei einem 50% PWM-Signal sieht das dann so aus:
Code:
1111100000
Ein 25% PWM-Signal sieht so aus (abgerundet, eigentlich 20%):
Code:
1100000000
Und dies wird dann wiederholt.
D.h.: Je grösser du die erste Zahl (On + Off) wählst, desto genauer bist du. Allerdings musst du dann aufpassen, dass die On- (oder Off) -Zeiten nicht zu gross werden (delay verkleinern/entfernen).
Je grösser die zweite Zahl, desto heller wird es.

PWM Signale werden generell als Frequenz- und Aktivzeit-Werten angegeben.
Z.B. ist ein 1kHz 50% PWM-Signal 500ms aktiv.
Um die Frequenz hoch zu bekommen, solltest du aber das delay() entfernen / stark verkleinern.
Das Problem mit wiringPI ist aber, dass du als Software gilts - wenn du zu viel CPU brauchst, wird dir Leistung weggenommen. Du musst ein bisschen probieren, wie's am besten geht.

Gruss
cwriter
 

einhuman197

Grünschnabel
Konnte mir inzwischen selbst helfen
C:
#include <stdio.h>
#include <wiringPi.h>

int zahl[10]={0,0,0,0,0,0,0,0,0,0};

void binaer (int wert)
{
   for (int i=0; i<10; i++)
   {
       zahl[i]=wert%2;
       wert=wert/2;
   }
}


int main(void)
{
   int pins[13] = {6,5,4,3,29,2,1,0,16,15,11,7,9};
   int p;
   int i;
   int j;
   int n;
   wiringPiSetup() ;
   for(p=0; p<10; p++)
   {
       pinMode (pins[p], OUTPUT);
       digitalWrite (pins[p], LOW);
   }

   for(i=0; i<=1000; i++)
   {
printf("Zahl: %d \n", i);
       for (n = 0; n < 10; n++)
       {
           binaer(i);
           for(j=0; j<13; j++)
               digitalWrite(pins[j], 0);
           delay(10);                           // Delay in Millisekunden
           for(j=0; j<13; j++)
               digitalWrite(pins[j], zahl[j]);            
           delay(2);                               // Delay in Millisekunden
           
       }
       
   }
   

   for(p=0; p<13; p++)
   {
       digitalWrite (pins[p], LOW);
   }   
}
 

einhuman197

Grünschnabel
Okay, hab inzwischen ein anderes Problem.
Ich soll die Schleifen zum schreiben der Werte auf die Pins in eine Funktion packen und jede ungerade Zahl soll gedimmt sein. Wie soll ich das denn auf die Reihe kriegen? Kann mir jemand helfen?
 

einhuman197

Grünschnabel
So, als Funktion hab ich das Dimmen impementiert nur das mit den ungeraden und geraden zahlen klappt nicht. Entweder alle zahlen sind gedimmt oder alle zahlen sind nicht gedimmt.
Hier mein Code mit Dimmen als Funktion:
Code:
#include <stdio.h>
#include <wiringPi.h>

int zahl[10]={0,0,0,0,0,0,0,0,0,0};

void binaer (int wert)
{
    for (int i=0; i<10; i++)
    {
        zahl[i]=wert%2;
        wert=wert/2;
    }
}

void gedimmt (int j)
{
    int pins[13] = {6,5,4,3,29,2,1,0,16,15,11,7,9};
            for(j=0; j<13; j++)
                digitalWrite(pins[j], 0);
            delay(10);                            // Delay in Millisekunden
            for(j=0; j<13; j++)
                digitalWrite(pins[j], zahl[j]);            
            delay(2);   
}

int main(void)
{
    int pins[13] = {6,5,4,3,29,2,1,0,16,15,11,7,9};
    int p;
    int i;
    int j=0;
    int n;
    wiringPiSetup() ;
    for(p=0; p<10; p++)
    {
        pinMode (pins[p], OUTPUT);
        digitalWrite (pins[p], LOW);
    }

    for(i=0; i<=1000; i++)
    {
printf("Zahl: %d \n", i);
        for (n = 0; n < 10; n++)
        {
            binaer(i);
            gedimmt(j);
           
        }
       
    }
   

    for(p=0; p<13; p++)
    {
        digitalWrite (pins[p], LOW);
    }   
}
Der funktioniert auch super.
Mein lösungsansatz war:

C:
if(i%2==1)
{
    gedimmt(j);
}
else
{
    for(j=0; j<13; j++)
    digitalWrite(pins[j], zahl[j]);
    delay(20)
}

Nur da spucken die LED's gar nichts aus. Hat jemand ne idee?
 

cwriter

Erfahrenes Mitglied
Nur da spucken die LED's gar nichts aus. Hat jemand ne idee?
Da ich den ganzen Code nicht sehe: Setzt du denn auch zahl[] korrekt, also nutzt binaer(i)?
Ansonsten ist das nicht wirklich gedimmt, was du machst.
Du müsstest die LEDs oft an- und wieder ausschalten, wie schon beschrieben.
 
Zuletzt bearbeitet:

einhuman197

Grünschnabel
Okay der Code läuft nun einwandfrei. Thx für die Hilfe
C:
#include <stdio.h>
#include <wiringPi.h>

int zahl[10]={0,0,0,0,0,0,0,0,0,0};

void binaer (int wert)
{
    for (int i=0; i<10; i++)
    {
        zahl[i]=wert%2;
        wert=wert/2;
    }
}

void gedimmt (void)
{
    int pins[13] = {6,5,4,3,29,2,1,0,16,15,11,7,9};
    int j;
    int n;
            for(n=0; n<10; n++)
            {
                for(j=0; j<13; j++)
                {
                    digitalWrite(pins[j], 0);
                   
                }   
                delay(20);                    // Delay in Millisekunden
                    for(j=0; j<13; j++)
                    {
                        digitalWrite(pins[j], zahl[j]);                    
                    }
                    delay(5);
            }   
}

int main(void)
{
    int pins[13] = {6,5,4,3,29,2,1,0,16,15,11,7,9};
    int p;
    int i;
    int j=0;
    int n;
    wiringPiSetup() ;
    for(p=0; p<10; p++)
    {
        pinMode (pins[p], OUTPUT);
        digitalWrite (pins[p], LOW);
    }

    for(i=0; i<=1000; i++)
    {

        printf("Zahl: %d \n", i);
        binaer(i);
        if((i%2)==1)
        {
            gedimmt();
        }
        else
        {
            for(n=0; n<10; n++)
            {
                for(j=0; j<13; j++)
                {
                digitalWrite(pins[j], zahl[j]);            
                }
                delay(25);
            }   
        }
    }
    for(p=0; p<13; p++)
    {
        digitalWrite (pins[p], LOW);
    }   
}