programování PWM

Odpovědět
daton
Příspěvky: 664
Registrován: 16 bře 2013, 16:12

programování PWM

Příspěvek od daton »

Zdravím
zkouším si programovat PWM ne dle funkce ale pomocí cyklů. Už jsem vytvořil základ ale bylo to moc rychlé tak jsem vložil cyklus do cyklu ale zde jsem narazil protože když jsem do cykli do whlie vložil for tak se mi nechce vykonat správně. Chová se to tak jako by tam v tom while žádná podminka nebyla skočí to hned na plnou uroven, chtěl jsem požádat zkušenější jestli tam nevidí ten zádrhel.

Kód: Vybrat vše

 i = 0;
    y=14;

do {
  for (j=0;j<25;j++){
  digitalWrite(13, HIGH);
  delay (i);
  digitalWrite (13,LOW);
  delay (15);}
  i++; }
  while (i == 12);
  j = 0;
  do {
    for (j=0;j<15;j++){
    digitalWrite (13,HIGH);
    delay (13);
    digitalWrite (13,LOW);
    delay (y);}
    y--;}
    while (y ==1);
   
}

daton
Příspěvky: 664
Registrován: 16 bře 2013, 16:12

Re: programování PWM

Příspěvek od daton »

Tak už to mám je to jen taková hříčka je k tomu potřeba jen arduino a prsty. Stačí spojit A7 s plusem a dioda na arduinu se pomalu rozsvítí jak kdyby byla řízena PWM z knihovny ale tady se dá vše nastavovat trochu víc. :D

Kód: Vybrat vše

int A;
int i;
int y;
int j;
void setup() {
  pinMode (13,OUTPUT);
  pinMode (A7, INPUT);
  
}

void loop() {
  A = analogRead(A7);
  if (A > 400) {
    i = 0;
    y=14;

do {
  do{
  digitalWrite(13, HIGH);
  delay (i);
  digitalWrite (13,LOW);
  delay (15);
  j++;  
  } while (j<7);
  i++; 
  j=0;}
  while (i< 12);
  j = 0;
  do {
    do{
    digitalWrite (13,HIGH);
    delay (13);
    digitalWrite (13,LOW);
    delay (y);
    j++;}while (j<6);
    j = 0;
    y--;}
   
    while (y >1);
    digitalWrite(13,HIGH);
    delay (2000);
    digitalWrite (13,LOW);
}
}
DavidO
Příspěvky: 1133
Registrován: 01 kvě 2013, 21:27

Re: programování PWM

Příspěvek od DavidO »

Vy už jste se dopracoval k něčemu funkčnímu, ale třeba se chcete Vy (nebo jiný čtenář) něco naučit, tak si to dovolím okomentovat:

V tom původním programu byl problém, že podmínka na konci do {} while () cyklu byla obráceně, mělo tam být spíš while( i != 12 ) nebo while( i < 12 ) když proměnná i jde odspodu. Tenhle typ cyklu totiž běží, dokud je podmínka je splněná, odpovídá to významu anglického slova "while" (na rozdíl třeba od Pascalu, kde je repeat ... until cyklus, který skončí, až když je podmínka splněná, neboli běží, dokud není podmínka splněná, což odpovídá zase významu "until". V češtině má while význam "zatímco", until "až", pro programování výstižněji while=dokud je, until=dokud není)

Ten kód je trochu hůř čitelný. V tomto případě bych raději psal cykly for, které jsou nakonec v těchhle běžných iteracích čitelnější, protože to důležité mají napsané na jednom místě. U do{}while() (anebo while(){}) cyklu musí někde být napsaná inicializace (třeba i=0), někde krok (i++) a někde podmínka (i<7), ale jazyk si nechá líbit, i když to bude po zdrojáku rozházené, jako třeba v tom Vašem.
Proměnné, které se používají jen jako pomocné (třeba pro řízení cyklů) v jedné funkci, by měly být v té funkci lokální (přesunout deklaraci A,i,j dovnitř loop). Dokonce je možné je deklarovat i jen pro ten cyklus takhle: for(byte i=0;i<12;i++), a pak použít jen uvnitř něj. Může to pomoct překladači pro snazší překládání a taky člověku, kdyby tu proměnnou omylem použil vně cyklu (kde to nedává smysl), tak překladač pozná, že to je chyba. Nicméně tady v tomhle prográmku to je skoro jedno.
Když se pin používá jako analogový, tak není potřeba ho nastavovat jako OUTPUT.
Pokud proměnná nabývá jen malých hodnot (0 až 255), stačí pro ní na malých Arduinech typ byte místo int, vykonávání je pak rychlejší a kód zabírá míň místa (malá Arduina mají základní datovou jednotku jednobytovou, ale int je dvoubytový, takže výpočty s ním se musejí dělat trochu složitěji; to sice člověk při psaní programu nevidí, zařídí to překladač, ale v principu je vhodné tomu zařízení trochu pomoct anebo aspoň nedělat mu špatně). Akorát je potřeba mít jistotu, že s každou proměnnou budu pracovat v rozsahu jejích možných hodnot, tj. do proměnné typu byte nikdy program nebude chtít dát záporná čísla nebo čísla větší než 255 (nebo je s takovými porovnávat), to by sice procesor přežil, ale výsledek by byl špatně. No a cykly v tomhle prográmku pracují s čísly od 0 do něco přes 10, to je pro byte OK. Úspora (paměť i čas) je možná nicotná, ale myslím, že je lepší dělat to pořádně než "tak nějak, ono to nevadí".

Co se týče významu kódu, pak bych se zeptal, jestli to přidávání "světla" ve 12 a následné ubírání "tmy" ve 13 krocích s vnitřním cyklem po 7 a 6 krocích s pevnou délkou čekání 15 a 13 ms plus variabilní 0 až 11 ms resp. 14 až 2 ms tak bylo myšleno, nebo jestli to byly tak nějak postupně naštelované konstanty. Já bych to asi psal tak, že dvojice čísel jsou stejné (12+12, 7+7, 15+15) a navíc jako nadefinované konstanty někde na začátku kódu, abych při změně nemusel procházet celý kód a měnit třeba 14 na 13 a pak na 12 kdyby to ještě bylo moc, přičemž bych si určitě (znám se) změnil 13 na 12 i v příkazu pro zapínání LEDdigitalWrite(13,HIGH) na digitalWrite(12,HIGH) a pak bych se divil, že to přestalo fungovat. Proto i pin, kam je zapojená LED, bych si udělal jako konstantu na začátku programu.

Ještě přidám trochu přepsaný kód, mělo by to dělat úplně to samé, ale snad trochu čitelněji:

Kód: Vybrat vše

#define LED 13
#define SPINAC A7

void setup() {
  pinMode(LED, OUTPUT);
}

void loop() {
  int A;
  byte i;
  byte j;  
  A = analogRead(SPINAC);
  if (A > 400) {
    for (i = 0; i < 12; i++) 
    {
      for (j = 0; j < 7; j++) 
      {
        digitalWrite(LED, HIGH);
        delay(i);
        digitalWrite(LED, LOW);
        delay(15);
      }
    }

    for(i=14;i>1;i--){
      for(j=0;j<6;j++){
        digitalWrite(LED,HIGH);
        delay(13);
        digitalWrite(LED,LOW);
        delay(i);
      }
    }
     
    digitalWrite(LED,HIGH);
    delay(2000);
    digitalWrite(LED,LOW);
  }
}
Tady ještě formátovací poznámka, v první části jsem to proložil víc mezerama, v druhé to je kompaktnější. Překladači to je jedno, záleží na tom, co je pro koho čitelnější, tady to dávám jen pro ukázku různých stylů.
Naposledy upravil(a) DavidO dne 05 kvě 2016, 13:00, celkem upraveno 1 x.
Nikoho plánovaně neurážím. Jestli se Vám nelíbí co píšu, tak to nečtěte. A ostatně, třeba za to nemůžu - Researchers believe that dark humor can be a significant symptom of dementia.
daton
Příspěvky: 664
Registrován: 16 bře 2013, 16:12

Re: programování PWM

Příspěvek od daton »

Zdravím moc děkuji za reakci s poučením. Snažím se pomocí takovýchto prográmku si nacvičit některé příkazy v tomto příkladě to byly cykly. Souhlasím s tím že for je lepší to že jsem použil while bylo právě pro procvičení. Ty konstatnty jsem doladil ručně aby si každý mohl bez dalších komponent pohrát jen s arduinem "bez drátku" a tedy to bylo odladěno na to aby se dioda na plošném spoji arduina pěkně postupně rozsvěcela a v níže uvedeném kodu i zhasínala (bez viditelného mrkání). Je mi jasné že to hodně závisí na druhu použitého světelného zdroje a tedy ty konstatny bude nutno rozhodně měnit pokud by někdo chtěl kody použít ve své aplikaci. Nejprve jsem totiž zkoušel i datové pole s přednastavenými hodnotami ale nakonec jsem dospěl k závěru že systém cyklů je lepší i když nevylučuji případy kdy bude naopak lepší datové pole pro snižování či zvyšování intenzity. Nemám zatím zkušenost s motory ale to bude možná přesně ten případ.
Ještě jen pro vyuku zde je to jen se dvěma cykly a využívá to funkce ale zase by to asi šlo napsat o hodně lépe.

Kód: Vybrat vše

int A;
int b;
int c;
int i;
int y;
int j;
void setup() {
 pinMode (13,OUTPUT);
}

int str (int i){
 b = constrain (i, 0,15);
 return b;}

void loop() {
  A = analogRead(A7);
  if (A > 400) {  i = 0;  y=30; b=0;

  do {
    
      do{
        digitalWrite(13, HIGH);
        delay (b);
        digitalWrite (13,LOW);
        delay (c);
        j++;  
      } while (j<7);
      
    i++; str (i);
    y--; c=y;j=0;
    if (c > 15) {c = 15;}
  } while (y>1);
  
    digitalWrite(13,HIGH);
    delay (2000);
    digitalWrite (13,LOW); 
} 

}
Odpovědět