luni, 26 decembrie 2016

OHMMETRU CU ARDUINO SI ADC ADS 1115

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.

Ce a iesit se poate vedea mai jos:













////



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