nico_2010 Postat August 5, 2015 Partajează Postat August 5, 2015 Daca nu te grasbesti prea mult, voi posta si un cod care sa-ti indeplineasca cerintele, numai ca acum sunt la serviciu. @ratza: pentru filtrare mai poate pune o celula de fitrare. Link spre comentariu
ratza Postat August 5, 2015 Partajează Postat August 5, 2015 Desigur, ce am propus eu era doar o altă variantă de obţinere a tensiunilor. Link spre comentariu
nico_2010 Postat August 5, 2015 Partajează Postat August 5, 2015 Si o varianta intermediara. Poate fi imbunatatita. byte buttons[] = {14, 15, 16, 17, 18, 19}; // intrari analogice cunoscute ca fiind 14-19byte outputs[] = {3, 5, 6, 9, 10, 11}; //porturile de iesireint lut[] = {10, 50, 100, 150, 200, 250}; // factori de umplereint value = 0;#define NUMBUTTONS sizeof(buttons)byte buttonState[NUMBUTTONS];byte buttonPressed[NUMBUTTONS];int val[NUMBUTTONS]; void setup() { // put your setup code here, to run once: byte i; for (i = 0; i < NUMBUTTONS; ++i) { pinMode(buttons[i], INPUT); digitalWrite(buttons[i], HIGH); pinMode(outputs[i], OUTPUT); } for (i = 0; i < NUMBUTTONS; ++i) { buttonState[i] = digitalRead(buttons[i]); } } void loop() { // put your main code here, to run repeatedly: buttonCheck(); // subrutina butoane for (byte i = 0; i < NUMBUTTONS; ++i) { if (buttonPressed[i]) { value = lut[i]; analogWrite(outputs[i-1], 0); analogWrite(outputs[i], value); } } } void buttonCheck() { for (byte i = 0; i < NUMBUTTONS; ++i) { val[i] = digitalRead(buttons[i]); if (val[i] != buttonState[i]) { if (val[i] == LOW) { buttonPressed[i] = 1; }else{ buttonPressed[i] = 0; } } buttonState[i]=val[i]; } } Link spre comentariu
mars01 Postat August 5, 2015 Partajează Postat August 5, 2015 (editat) Nico, poate ii pui si debounce la butoane altfel o sa ii faca in toate felurile. for (byte i = 0; i < NUMBUTTONS; ++i) { if (buttonPressed[i]) {value = lut[i];analogWrite(outputs[i-1], 0);analogWrite(outputs[i], value); O alta mica problema este ca tu dezactivezi doar valoarea iesirii corespunzatore butonului precedent ca ordine. Daca butonul apasat anterior a fost 3 iar acum se apasa butonul 4 va merge in regula. Dar daca mai intai a fost apasat sa zicem butonul 1 iar acum butonul 5, tu faci zero pe valoarea iesire corespunzatoare butonului 4 si activezi valoarea iesire atasata buton 5. Probabil trebuie sa tii minte ce buton a fost apasat anterior. LE: In plus, din cate spune OP: Trebuie doar sa simta ca s-a apasat butonul 1, 2, 3, 4, 5 sau 6 iar la sfarsitul montajului, in functie de pinul apasat pe cele doua fire despre care spuneam mai sus sa imi apara tensiunea ce corespunde butonului. Editat August 5, 2015 de mars01 Link spre comentariu
lutza2 Postat August 5, 2015 Partajează Postat August 5, 2015 Misto subiect. O sa incerc si eu ca pare foarte bun pentru practica. Cifrele la factorii de umplere reprezinta procentaje sau cifre , adica pentru 10 corespunde 0% si pentru 250 corespunde 100% ? Daca ultima tensiune e 5V nu se poate ca pinul sa nu mai scoata pwm ci direct high ? De fiecare data se scaneaza intr-o bucla for toate butoanele. Am incercat si eu o chestie cu 3 butoane si cu if-uri imbricate si recunosc ca nu arata elegant deloc codul cu toate ca mergea. Exista o functie in genul case care sa nu mai scaneze toate butoanele ? Intreb in principiu, nu referitor la programul prezentat. Link spre comentariu
nico_2010 Postat August 5, 2015 Partajează Postat August 5, 2015 Cum ziceam, solutia este perfectibila. Se poate si cu "case". Link spre comentariu
ratza Postat August 6, 2015 Partajează Postat August 6, 2015 Dacă eşti suficient de nebun, se poate şi cu array de funcţii. Link spre comentariu
nico_2010 Postat August 6, 2015 Partajează Postat August 6, 2015 Si o varianta cu debounce si 'case": #define DEBOUNCE 10 // timp alocat pentru debounce //definirea porturilor pentru butoanebyte buttons[] = {14, 15, 16, 17, 18, 19}; #define NUMBUTTONS sizeof(buttons)byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS]; void setup() { byte i; // Setari de porturi pentru butoane for (i=0; i< NUMBUTTONS; i++) { pinMode(buttons[i], INPUT); digitalWrite(buttons[i], HIGH); }} void loop() { byte thisSwitch=thisSwitch_justPressed(); switch(thisSwitch) { case 0: analogWrite(3,10); break; case 1: analogWrite(5,50); break; case 2: analogWrite(6,100); break; case 3: analogWrite(9,150); break; case 4: analogWrite(10,200); break; case 5: analogWrite(11,250); break; default: ; }} void check_switches() // subrutina de verificare periodica a starii butoanelor{ static byte previousstate[NUMBUTTONS]; static byte currentstate[NUMBUTTONS]; static long lasttime; byte index; if (millis() < lasttime) { lasttime = millis(); } if ((lasttime + DEBOUNCE) > millis()) { // nu a trecut suficient timp pentru debounce return; } // a trecut suficient timp pentru debounce lasttime = millis(); for (index = 0; index < NUMBUTTONS; index++) { justpressed[index] = 0; justreleased[index] = 0; currentstate[index] = digitalRead(buttons[index]); //citire butoane if (currentstate[index] == previousstate[index]) { if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { justpressed[index] = 1; } else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { justreleased[index] = 1; } pressed[index] = !currentstate[index]; } previousstate[index] = currentstate[index]; }} byte thisSwitch_justPressed() { byte thisSwitch = 255; check_switches(); for (byte i = 0; i < NUMBUTTONS; i++) { current_keystate[i]=justpressed[i]; if (current_keystate[i] != previous_keystate[i]) { if (current_keystate[i]) thisSwitch=i; } previous_keystate[i]=current_keystate[i]; } return thisSwitch;} Sincer, ma asteptam ca in afara de sfaturi si idei sa vad si alte abordari. dar este bine si asa. Nu pretind ca varianta asta este cea mai buna sau perfecta, insa raspunde in mare masura cerintelor enuntate de initiatorul topicului. Link spre comentariu
mars01 Postat August 6, 2015 Partajează Postat August 6, 2015 (editat) M-am pierdut putin printre toate starile astea, variabile index si tot asa, dar o mica problema tot o pot semnala. Ar trebuie declarata o alta arie avand ca elemente iesirile PWM. Eventual facuta o functie care scrie duty cycle nul pe toate iesirile PWM. Iar in structura switch ... case , pe fiecare ramura inainte de a scrie factorul de umplere (duty cycle) pentru iesirea corespunzatoare, apelezi functia care face zero pe iesirile PWM. In felul acesta te asiguri ca iesirile anterior activate sunt dezactivate si ramane activa (cu factor de umplere diferit de zero) doar iesirea ce urmeaza sa fie activata. Cum este acum, daca apesi secvential pe toate cele 6 butoane vei ramane in final cu 6 iesiri simultan active, fiecare cu factorul sau de umplere, deci cu tensiunea sa dupa filtrarea low pass. As adauga/schimba ceva de genul: byte outputs[] = { 3, 5, 6, 9, 10, 11 };void loop(){ byte thisSwitch = thisSwitch_justPressed(); switch (thisSwitch) { case 0: nullify(); analogWrite(3, 10); break; case 1: nullify(); analogWrite(5, 50); break; case 2: nullify(); analogWrite(6, 100); break; case 3: nullify(); analogWrite(9, 150); break; case 4: nullify(); analogWrite(10, 200); break; case 5: nullify(); analogWrite(11, 250); break; }}void nullify(){ byte i = 5; do { analogWrite(outputs[i], 0); } while (i--);} Si se adauga restul programului facut de tine. Editat August 6, 2015 de mars01 Link spre comentariu
nico_2010 Postat August 6, 2015 Partajează Postat August 6, 2015 Da, ar fi frumos sa fie doar atat. Insa in momentul in care faci duty cycle = 0 vei obtine o tensiune nula (e un fel de a spune, undeva la 0.1-0.2V) pe pinul respectiv, care va afecta tesiunea finala la iesire. Din pacate Arduino nu are o functie de anulare a semnalului PWM si de trecere a pinului cu pricina in intrare Hi-Z. Asta nu inseamna ca nu se poate atinge acest scop prin software. L.E.: Am modificat putin rutina nullify, in sensul celor de mai sus: void nullify(){ byte i = 5; do { pinMode(outputs[i], INPUT); } while (i--);} si acum se comporta asa cum ar trebui. Link spre comentariu
mars01 Postat August 6, 2015 Partajează Postat August 6, 2015 (editat) In acest caz trebuie schimbata si structura switch case din loop() cam asa (functia analogWrite are nevoie de declaratie a pinului ca iesire): void loop(){ byte thisSwitch = thisSwitch_justPressed(); switch (thisSwitch) { case 0: nullify(); //pinMode(3, OUTPUT); analogWrite(3, 10); break; case 1: nullify(); //pinMode(5, OUTPUT); analogWrite(5, 50); break; case 2: nullify(); //pinMode(6, OUTPUT); analogWrite(6, 100); break; case 3: nullify(); //pinMode(9, OUTPUT); analogWrite(9, 150); break; case 4: nullify(); //pinMode(10, OUTPUT); analogWrite(10, 200); break; case 5: nullify(); //pinMode(11, OUTPUT); analogWrite(11, 250); break; }} Editat August 6, 2015 de mars01 Link spre comentariu
nico_2010 Postat August 6, 2015 Partajează Postat August 6, 2015 Nu este nevoie de modificarea structurii switch-case, deoarece apelarea comenzii "analogWrite" nu presupune declararea pinilor ca output. Forma finala a sketch-ului: #define DEBOUNCE 10 // timp alocat pentru debounce //definirea porturilor pentru butoanebyte buttons[] = {14, 15, 16, 17, 18, 19}; byte outputs[] = { 3, 5, 6, 9, 10, 11 };#define NUMBUTTONS sizeof(buttons)byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS]; void setup() { byte i; // Setari de porturi pentru butoane for (i=0; i< NUMBUTTONS; i++) { pinMode(buttons[i], INPUT); digitalWrite(buttons[i], HIGH); }} void loop() { byte thisSwitch=thisSwitch_justPressed(); switch(thisSwitch) { case 0: nullify(); analogWrite(3, 10); break; case 1: nullify(); analogWrite(5, 50); break; case 2: nullify(); analogWrite(6, 100); break; case 3: nullify(); analogWrite(9, 150); break; case 4: nullify(); analogWrite(10, 200); break; case 5: nullify(); analogWrite(11, 250); break; default: ; }} void check_switches() // subrutina de verificare periodica a starii butoanelor{ static byte previousstate[NUMBUTTONS]; static byte currentstate[NUMBUTTONS]; static long lasttime; byte index; if (millis() < lasttime) { lasttime = millis(); } if ((lasttime + DEBOUNCE) > millis()) { // nu a trecut suficient timp pentru debounce return; } // a trecut suficient timp pentru debounce lasttime = millis(); for (index = 0; index < NUMBUTTONS; index++) { justpressed[index] = 0; justreleased[index] = 0; currentstate[index] = digitalRead(buttons[index]); //citire butoane if (currentstate[index] == previousstate[index]) { if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { justpressed[index] = 1; } else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { justreleased[index] = 1; } pressed[index] = !currentstate[index]; } previousstate[index] = currentstate[index]; }} byte thisSwitch_justPressed() { byte thisSwitch = 255; check_switches(); for (byte i = 0; i < NUMBUTTONS; i++) { current_keystate[i]=justpressed[i]; if (current_keystate[i] != previous_keystate[i]) { if (current_keystate[i]) thisSwitch=i; } previous_keystate[i]=current_keystate[i]; } return thisSwitch;}void nullify(){ byte i = 5; do { pinMode(outputs[i], INPUT); } while (i--);} Link spre comentariu
lutza2 Postat August 6, 2015 Partajează Postat August 6, 2015 (editat) Merci nico, chiar vroiam sa te rog pentru un exemplu. Nu-mi era clar daca trebuie sa detectezi evenimentul si sa intri apoi in case sau nu. E de studiat. Alte abordari, din partea mea, sper, dupa ce mai tii niste cursuri. Pentru mine e foarte util. Multumiri inca o data si lui mars deasemenea. Editat August 6, 2015 de lutza2 Link spre comentariu
nico_2010 Postat August 7, 2015 Partajează Postat August 7, 2015 Multumirile ar trebui sa mearga mai mult spre mars01 decat spre mine. Link spre comentariu
mars01 Postat August 7, 2015 Partajează Postat August 7, 2015 (editat) Multumesc Nico pentru apreciere dar contributia mea este minora, munca tu ai facut-o. Intodeuna este mai usor sa stai si sa "pigulesti" dupa ce altul a facut greul. Oricum, ma bucura ca incepem si noi aici pe elforum sa ajutam pe cei care sunt la inceput, cu exemple de coduri sursa. Ca un mic off topic. La un moment dat am primit o instiintare, un newsletter de fapt, ca urma sa fie un curs interesant pe embedded. Participare gratis, mai ofereau si ceva placa de dezvoltare ... Eu deja interesat. Mai pe urma observ ca se organiza in Polonia. Si reflectam atunci cum toate evenimentele ne ocolesc pe noi, romanii. Avem potential dar totusi firmele mari abia in ultima vreme au inceput sa vina in Romania si mai ales in Vest, zona Timis-ului. Si de la una la alta, ma gandeam daca nu ar fi bine ca din putinul care il stiu sa ofer si altora. Probabil ca pe urma apar si alte persoane care vor ajuta si tot asa, vom ajunge si noi sa concuram cu ceilalti din zona. Hai sa pornim bolovanul la vale ... Editat August 7, 2015 de mars01 Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum