Sari la conținut
ELFORUM - Forumul electronistilor

6 tensiuni intre 0-5v


Vizitator Laurentiu Dumitras

Postări Recomandate

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
  • Răspunsuri 30
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • nico_2010

    11

  • mars01

    5

  • one

    3

  • ratza

    3

Top autori în acest subiect

Imagini postate

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

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 de mars01
Link spre comentariu

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

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

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 de mars01
Link spre comentariu

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

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 de mars01
Link spre comentariu

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

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 de lutza2
Link spre comentariu

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 de mars01
Link spre comentariu

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 cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări