Salutare tuturor !
Iata ca printre toate problemele pe care le-am avut in ultima parte a acestui an am gasit ragazul sa mai adaug un articol pe blog. Urmatoarul proiect izvoraste mai mult dintr-o necesitate aparuta la locul de munca.
Asadar ohmmetrul prezentat in cele urmeaza va fi folosit pentru testarea la rece a unor tablouri electrice utilizate in cadrul automatizarilor navale. Bineinteles ca va veti intreba (si asta pe buna dreptate) de ce nu este protivita utlizarea unui ohmmetru obisnuit. Raspunsul este simplu: datorita numarului mare de conexiuni care trebuie testate nu este timp pentru a citi de fiecare data indicatia instrumentului de masura, asa ca beeper-ul este cel care dicteaza corectitudinea unui traseu. Aparatul de masura "piuie" pentru o rezistenta in intrvalul 0-100 ohmi. Cum avem componente a caror impedanta de intrare este de ordinul zecilor de ohmi, uneori se poate ca "piuitul" sa nu indice corect continuitatea unui traseu.
Schema electrica...
Pentru proiectul in cauza am decis sa utilizez un Arduino Uno (ma rog o clona...) si 2 componente cheie:
- LM317 - ca generator de curent constant;
- ADS 1115 - convertor analog digital cu interafata I2C.
Mai jos se poate vedea schema electrica:
Am decis sa folosesc doua domenii de masura : 0-100 ohmi si 100-1M. Selectia domeniilor se face cu ajutorul comutatorlui dublu SW1, iar conectarea in circuit a rezistentei ce e doresete a fi masurata se face prin intermediul conectorului J6. Functonarea va fi prezentata in randurile de mai jos:
- Cand SW1 este in prima pozitie, se utilizeaza primul domeniu de masura. LM317 este alimentat la 5V si datorita configuratiei de generator de curent constant va incerca sa debiteze aproximativ 12.5 mA (1.25V cadere de tensiune constanta pe R1). Intrarea anologica A0 a lui ADS1115 citeste caderea ce tensiune pe rezistenta necunoscuta iar A1 citeste tensiunea pe care o da la iesire LM-ul. In urma catorva calcule simple (legea divizorului de tensiune) se determina rezistenta necunoscuta.
- Cand SW2 este in cea de-a doua pozitie se alimenteaza cu 5V rezistorul R2 (10k). Intrarea analogica A2 a lui ADS1115 citeste tensiunea de alimentare (NU ESTE 5V FIX - NICIODATA!!!) iar A0 citeste caderea de tensiune pe rezistenta necunoscuta. Si in acest caz se utilizeaza legea divizorului de tensiune pentru determiarea rezistorului necunoscut.
- In colectorul tranzistorului Q1 se conecteaza un buzzer care va "piui" numai daca rezistenta este mai mica de 3 ohmi.
- Afisarea datelor este facuta pe un LCD cu doua randuri si 16 coloane care utilizeaza o iterfata I2C. Daca timp de 15 secunde nu se face nici o citire atunci backlight-ul LCD-ului se va inchide automat, pentru economisirea bateriei.
De ce nu am utlizat ADC-ul lui Arduino?
Adc-ul pe care il ofera Arduino este bun numai pentru estimari aproximative. In general nu este stabil pentru tensiunea de referinta nu este stabila. Daca nu ma credeti masurati... Tensiunea de 5V variaza in limite destul de mari ceea ce face imposibila determinarea cu exactitate a cuantei. Este mult de discutat vis-a-vis de acest subiect foarte interesat si poate o data va face obiectul unui articol.
Incepand cu acest proiect am decis sa "imi produc" singur shieldurile pentru Arduino. Cablajul este prezentat in imaginea de mai jos:
Bineinteles ca LCD-ul si comutatorul dublu cu doua pozitii vor fi montate pe carcasa.
Codul pentru Arduino...
In mare nu este ceva foarte complicat. Nu am facut altceva decat sa transpun in cod legea divizorului de tensiune:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | #include <Wire.h> #include <Adafruit_ADS1015.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); Adafruit_ADS1115 ads(0x48); unsigned long t; boolean check=true; byte ohm[] = { B00000, B01110, B10001, B10001, B01010, B01010, B11011, B00000 }; String empty=" "; float Vo = 0.0;//voltage in float Vref = 0.0;//voltage drop on unknown resitor int domain = 7; //digitalRead() of domain int buzz=9;// buzzer float crt;// current flowing through resitor float res; //unknown resitor String sres; //string casting of unknown reistor String s; // string of domain void setup(void) { pinMode(buzz, OUTPUT); pinMode(domain, INPUT); Serial.begin(9600); ads.begin(); lcd.init(); lcd.createChar(0, ohm); lcd.backlight(); lcd.setCursor(0,0); lcd.print("DIGITAL OHMMETER"); lcd.setCursor(2,1); lcd.print("hobbyelectro"); delay(2000); lcd.clear(); lcd.setCursor(0,0); lcd.print("Firmware 1.0"); lcd.setCursor(2,1); } boolean getDomain() { if (digitalRead(domain)) { return true; } return false; } void printData() { /*Serial.print("DOMENIU-->"); Serial.print(s); Serial.print("\tVo: "); Serial.print(Vo, 9); Serial.print("\tVref: "); Serial.print(Vref, 9); Serial.print("\tCurrent: "); Serial.print(crt, 9); Serial.print("\t"); Serial.print("\tResistor: "); Serial.println(sres);*/ } void printLcd(){ lcd.backlight(); lcd.setCursor(0,0); String data=s+" "+"R="+sres; lcd.print(data); int len =data.length(); lcd.setCursor(len,0); lcd.write(byte(0)); lcd.setCursor(len+1,0); lcd.print(empty); lcd.setCursor(0,1); String v="Vo="+String(Vo)+"V"+" "+"Vd="+String(Vref)+"V"+empty; lcd.print(v); check=true; t=millis(); } void lcdOut(){ //lcd.clear(); lcd.setCursor(0,0); lcd.print("Out of range..."+empty); lcd.setCursor(0,1); lcd.print(empty); } void checkData(boolean d) { if(res<1.00){ sres="0.00"; } if (d) { if (res < 120) { printData(); printLcd(); if(res<3.00){ analogWrite(buzz,1); delay(100); analogWrite(buzz,5); delay(100); analogWrite(buzz,20); delay(100); analogWrite(buzz,5); delay(100); analogWrite(buzz,1); delay(100); analogWrite(buzz,0); } } else { Serial.println("OUT OF RANGE ..."); lcdOut(); } } else { if (res>120 && res < 1000000) { printData(); printLcd(); } else { Serial.println("OUT OF RANGE ..."); lcdOut(); } } } void getResistor() { int16_t adc0 = ads.readADC_SingleEnded(0); //get adc for voltage drop on unknown resitor Vref = (adc0 * 0.1875) / 1000; int16_t adc1;//get adc for supply voltage from LM317 int16_t adc2;//get adc for supply voltage for 10k resistor int16_t divider; delay(50); boolean d = getDomain(); if (d) { adc1 = ads.readADC_SingleEnded(1); delay(50); Vo = (adc1 * 0.1875) / 1000; divider = 100.5; s = "D1 "; } else { adc2 = ads.readADC_SingleEnded(2); delay(50); Vo = (adc2 * 0.1875) / 1000; divider = 10000; s = "D2 "; } if (Vo > Vref) { crt = (Vo - Vref) / divider; res = abs((Vref / crt) - 0.3); if (res > 999) { sres = String(res / 1000) + "k"; } else { sres = String(res); } checkData(d); } else { Serial.println("OUT OF RANGE..."); lcdOut(); } } void loop(void) { if(check){ t=millis(); check=false; } getResistor(); if((millis()-t)>15000){ lcd.clear(); lcd.noBacklight(); } delay(1000); } |
Cam atat pentru articolul de azi.
Cum sfarsitul de an se apropie, va urez pentru 2017 sanatate, bucurii si la cat mai multe proiecte de electronica finalizate!
Sa auzim de bine!
Niciun comentariu:
Trimiteți un comentariu