Author Topic: Amp/Volt Meter with Fan Controller  (Read 1248 times)

0 Members and 1 Guest are viewing this topic.

Offline asokolsky

  • Newbie
  • Posts: 4
  • Country: us
Amp/Volt Meter with Fan Controller
« on: June 25, 2018, 12:25:23 pm »
This is still in planning phase..
ACS711EX for current sensing, ADS1115 for 15bit ADC and Arduino to drive display (I2C OLED) and a fan (via ULN2003)
Your feedback will be appreciated.

https://easyeda.com/asokolsky/AmpVolt-Meter-with-Fan-Control

Alex
 

Offline perieanuo

  • Regular Contributor
  • *
  • Posts: 150
  • Country: fr
Re: Amp/Volt Meter with Fan Controller
« Reply #1 on: June 25, 2018, 04:28:31 pm »
I made a variable linear power supply 0-30V 0-10A and course I made also an amp/voltmeter with an arduino mini pro.
I show current (A, 2 decimals) and Voltage (2 decimals) on oled display SH1106 MODULE ECRAN LCD OLED pour ARDUINO 1.3 POUCES .
Current measurement is done with arduino module ACS712 30A (listen, I was to lazy to make an dedicated board with the atmega and the Oled and the sensor).
voltage measurement is done with the arduino mini pro himself :) .IMHO the voltage measurement is precise enough.
Concerning current, the ACS712 is a piece of s..it, it changes the offset current when is a little hot (it has usually 120-140 mA offset, I had to ""decide" the offset current when starting the ACS module otherwise you see what gigantic errors you get...).You can avoid this...There are some professional current detectors on the market you can choose.And cherry on the cake Allegro said:"For existing customer transition, and for new customers or new applications, use ACS723."
So do you really need the voltage precision (or current)?Beside, I don't know if the ADS1115 isn't another bad surprise like the ACS712.Normally, TI make good products, so the 1115 should do fine, if you REALLY need the precision.
Anyway you have to 'calibrate' the V and I readings.
I can share the arduino sketch if you want, it works from some time (I had to deactivate the reset pin I had some resets on the mini pro... and wanted to be a little industrial performance).
Edit 1:Are you sure 0.96 isn't tooo little?See here the 1.3 oled.
Edit 2: you don't need UDN/ULN stuff, just pout some npn.
Edit 3: I don't get the 2xoled idea, why complicate the things?Then you need to do 2 windows in the case, 2 fixations, more wires.One display is not a better solution?
To be continued I hope,

Best regards, Ovidiu
« Last Edit: June 25, 2018, 04:47:49 pm by perieanuo »
 

Offline asokolsky

  • Newbie
  • Posts: 4
  • Country: us
Re: Amp/Volt Meter with Fan Controller
« Reply #2 on: June 26, 2018, 05:36:04 am »
Thank you, Ovidiu!
Happy to hear you tried similar things.

I have no experience yet with ACS711.  I ordered from Pololu: https://www.pololu.com/product/2452 and it refers to ACS711KEXLT-15AB-T which has 90 mV/A sensitivity.
Replacing it with ACS723, e.g. https://www.sparkfun.com/products/13679 which according to photo uses ACS723LLCTR-05AB-T2 which in turn has sensitivity 400 mV/A, may indeed render 16bit ADC unnecessary.
Thank you for the pointer!

I need ADC to measure current sensor output, voltage, temperature sensor output - the latter LM35 has 0-1V output range with 10mV/C sensitivity.  I thought using an external 16bit ADC would solve all this nicely.
I admit I have no experience with ADS1115.

> Are you sure 0.96 isn't tooo little?See here the 1.3 oled.
> I don't get the 2xoled idea
Agreed. 
The PCB is designed for I2C and SPI OLEDs.  Both .96" and 1.3" will work. 
Just one at a time, so those are mutually exclusive.  I will make relevant clarifications in the schematics.

> you don't need UDN/ULN stuff, just pout some npn.
True. 
But then you need to include a fly-by diode.  Besides I already use ULN part in my fan controller:
https://easyeda.com/asokolsky/Fan_Controller-0c20aa3afe5045e5a980d684715a4248
https://github.com/asokolsky/FanController

> I can share the arduino sketch if you want,
If it is public, I would love to look at it!

Thank you again for the pointer to ACS723. I ordered that breakout from SparkFun.

Cheers!




« Last Edit: June 26, 2018, 07:02:22 am by asokolsky »
 

Offline perieanuo

  • Regular Contributor
  • *
  • Posts: 150
  • Country: fr
Re: Amp/Volt Meter with Fan Controller
« Reply #3 on: June 26, 2018, 03:37:18 pm »
hi,
here's the code
it's really basic and do the job.
It can be simplified further more or add power measurement, I choose not to calculate/print power.
The ADS1115 is just used as multiplexer, so don't worry for him.I just consider you overshot using it regarding you have 6 analog pins on pro mini
and you don't have hard time ADC problems.
Basically I was just trying to restrain to the minimum the stuff needed.
But with a more quick and precise ADC solution you can do maybe more.

Here's the code, I guarantee it works.
And as a little advice disable the reset pin in fuses or just pull him hard to Vcc(I just put Vcc on RES pin).
Reason: you have to decide error for V and I at start and with my code if the module restarts, the measured I is considered as offset.

Code: [Select]


#include <Arduino.h>
#include <U8x8lib.h>
#include <string.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

void setup() {

  Serial.begin(9600);
 
  u8x8.begin();
  u8x8.setPowerSave(0);
  u8x8.setFont(u8x8_font_chroma48medium8_r);

  //corectie offset senzor curent ACS712,ruleaza o sg data la pornire
                        float AcsOffset=0.0,SamplesOffset=0.0,AvgAcsOffset=0.0,AcsValueOffset=0.0;
                       
                          for (int k = 0; k < 100; k++){ //Get 150 samples
                          AcsValueOffset = analogRead(A3);                  //Read current sensor values
                          SamplesOffset = SamplesOffset + AcsValueOffset;   //Add samples together
                          delay (3);                                        // let ADC settle before next sample 3ms
                          }
                        AvgAcsOffset=SamplesOffset/100;                      //Taking Average of Samples
                       
                        double VccOffset,vccOffset;
                        VccOffset = readVcc()/1000.0;                       //Arduino voltage(Acs712 supplied voltage - Operating voltage);1000>cred ca citeste in mV !
                        vccOffset=VccOffset/2.0;                            //Reference Voltage
                                                                            //((AvgAcs * (5.0 / 1024.0)) is converitng the read voltage in 0-5 volts
                                                                            //2.5 is offset(I assumed that arduino is working on 5v so the viout at no current comes
                                                                            //out to be 2.5 which is out offset. If your arduino is working on different voltage than
                                                                            //you must change the offset according to the input voltage)
                                                                            //0.185v(185mV) is rise in output voltage when 1A current flows at input
                                                                           
                        AcsValueOffset = (vccOffset - (AvgAcsOffset * (VccOffset / 1024.0)) )/0.100;
                        Serial.print("I_Offset_boot=");Serial.println(AcsValueOffset);
                        delay(10);
                       
    /*
    // optional print I_Offset
       
                  u8x8.setFont(u8x8_font_chroma48medium8_r);
                 
                  u8x8.setCursor(1,0);
                            u8x8.print("IoffS=");
                            delay(10);
                            u8x8.print(AcsValueOffset,3);
                            u8x8.print("A");
                            delay(10);
                            Serial.print("I_Offset_setup=");Serial.println(AcsValueOffset);
                            delay(10);
                           
                            delay(1000);
                            u8x8.clear();
                            delay(10);
    //final citire curent I_Offset 
    */

    u8x8.draw2x2String(0,0," Power");
    delay(100);
    u8x8.draw2x2String(0,2," Supply");
    delay(200);
    u8x8.draw2x2String(0,4,"   v4");
    delay(500);
    uint8_t tiles[16] = { 0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0, 1, 3, 7, 15, 31, 63, 127, 255};
    for (int j = 0; j<= 14 ; j++){
      u8x8.drawTile(j , 6, 2, tiles); //x0,y0,tile_tip>de la 1-7 cred
      delay(10);
    }   
    delay(1000);
   
   
   if (AcsValueOffset>0.18){
       for(int j=1 ; j <= 3 ; j++){
         u8x8.clear();
         delay(1000);
         u8x8.setCursor(1,0);
         u8x8.draw2x2String(1,1,"REMOVE  ");
         u8x8.setCursor(1,4);
         u8x8.draw2x2String(1,3," LOAD ");
         delay(1000);
    }
   }
   delay(1000);
   u8x8.clear();
   delay(10);
}
long readVcc() {
                // Read 1.1V reference against AVcc
                // set the reference to Vcc and the measurement to the internal 1.1V reference
                #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
                  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
                #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
                  ADMUX = _BV(MUX5) | _BV(MUX0);
                #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
                  ADMUX = _BV(MUX3) | _BV(MUX2);
                #else
                  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
                #endif 
             
                delay(2); // Wait for Vref to settle
                ADCSRA |= _BV(ADSC); // Start conversion
                while (bit_is_set(ADCSRA,ADSC)); // measuring
             
                uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH 
                uint8_t high = ADCH; // unlocks both
             
                long result = (high<<8) | low;
             
                result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
                return result; // Vcc in millivolts
}


void loop() {
                       
                        Serial.begin(9600);     //pt pb afisare I_Offset
    //corectie offset senzor curent ACS712,ruleaza o sg data la pornire

                        float AcsOffset=0.0,SamplesOffset=0.0,AvgAcsOffset=0.0,AcsValueOffset=0.0;
                       
                          for (int k = 0; k < 100; k++){ //Get 100 samples
                          AcsValueOffset = analogRead(A3);                  //Read current sensor values
                          SamplesOffset = SamplesOffset + AcsValueOffset;   //Add samples together
                          delay (3);                                        // let ADC settle before next sample 3ms
                          }
                        AvgAcsOffset=SamplesOffset/100;                      //Taking Average of Samples

    //stabilire tensiune echivalenta cu I=0 ( uzual 2,5V = 1/2 * 5V )
                        double VccOffset,vccOffset;
                        VccOffset = readVcc()/1000.0;                       //Arduino voltage(Acs712 supplied voltage - Operating voltage);1000>cred ca citeste in mV !
                        vccOffset=VccOffset/2.0;                            //Reference Voltage
                                                                            //((AvgAcs * (5.0 / 1024.0)) is converitng the read voltage in 0-5 volts
                                                                            //2.5 is offset(I assumed that arduino is working on 5v so the viout at no current comes
                                                                            //out to be 2.5 which is out offset. If your arduino is working on different voltage than
                                                                            //you must change the offset according to the input voltage)
                                                                            //0.185v(185mV) is rise in output voltage when 1A current flows at input
                                                                           
                        AcsValueOffset = (vccOffset - (AvgAcsOffset * (VccOffset / 1024.0)) )/0.100;
                           
/*                           bool Load = false;
                           if (AcsValueOffset>0.18){
                              bool Load = true;
                            }
                            Serial.print(Load);*/
                        delay(10);

    //  print I_Offset pe LCD, doar dupa start sau reset board

                        u8x8.setFont(u8x8_font_chroma48medium8_r);
                        u8x8.setCursor(0,8);
                        u8x8.print("Ioff = ");
                        delay(10);
                        u8x8.print(AcsValueOffset,2);
                        u8x8.print(" A");
                        delay(10);
                        Serial.print("I_Offset_loop=");Serial.println(AcsValueOffset);
                        delay(10);

//  intrare in ciclul "principal"

            while(1){
                                       
             //mediere curent I
                        float AcsValue=0.0,Samples=0.0,AvgAcs=0.0,AcsValueF=0.0;
                       
                          for (int x = 0; x < 150; x++){   //Get 150 samples
                          AcsValue = analogRead(A3);      //Read current sensor values
                          Samples = Samples + AcsValue;   //Add samples together
                          delay (3);                      // let ADC settle before next sample 3ms
                          }
                        AvgAcs=Samples/150;                //Taking Average of Samples
                       
                        double Vcc,vcc;
                        Vcc = readVcc()/1000.0;   //Arduino voltage(Acs712 supplied voltage - Operating voltage)
                        vcc=Vcc/2.0;              //Reference Voltage
                        //((AvgAcs * (5.0 / 1024.0)) is converitng the read voltage in 0-5 volts
                        //2.5 is offset(I assumed that arduino is working on 5v so the viout at no current comes
                        //out to be 2.5 which is out offset. If your arduino is working on different voltage than
                        //you must change the offset according to the input voltage)
                        //0.185v(185mV) is rise in output voltage when 1A current flows at input
                       
                        AcsValueF = (vcc - (AvgAcs * (Vcc / 1024.0)) )/0.100;
                        AcsValueF = AcsValueF - AcsValueOffset;      //corectie offset senzor curent ACS712
                //final mediere curent
                        AcsValueF = abs(AcsValueF); //elimin semn - masor doar curent pozitiv
/*
                //curent ne-mediat
                        float AcsValueF=0.0;
                        AcsValueF = analogRead(A3);
                        double Vcc,vcc;
                        Vcc = readVcc()/1000.0;   //Arduino voltage(Acs712 supplied voltage - Operating voltage)
                        vcc=Vcc/2.0;              //Reference Voltage
                        //((AvgAcs * (5.0 / 1024.0)) is converitng the read voltage in 0-5 volts
                        //2.5 is offset(I assumed that arduino is working on 5v so the viout at no current comes
                        //out to be 2.5 which is out offset. If your arduino is working on different voltage than
                        //you must change the offset according to the input voltage)
                        //0.185v(185mV) is rise in output voltage when 1A current flows at input
                       
                        AcsValueF = (vcc - (AcsValueF * (Vcc / 1024.0)) )/0.100;
                        AcsValueF = AcsValueF - AcsValueOffset;      //corectie offset senzor curent ACS712
                 //final curent ne-mediat
*/                       
                        float Vin=0;
                        float Rdown=2200;
                        float Rup=10000;
                        float k_divider=1;
                        float k_calibrare = 23.68/22.77 ;      //CA5275 23.67 ; Fluke:20V fluke=19.28V Oled->20.00/19.28
                        k_divider= (Rup+Rdown) / Rdown ;
                        float k = 1;                    //Divizor 2K2 JOS/ 10K SUS//ERA
                        k= 5* k_divider;
                        k = k * k_calibrare;

                        //mediere tensiune
                        float SamplesV=0;
                        for (int y = 0; y < 150; y++){
                        Vin = analogRead(A2);           
                        Vin = Vin * k /1024 ;           //formula originala:V=(analog_value*Vcc)/1024 unde: Vcc=5V pt Atmega328,1024=rezolutie ADC 10 biti
                        SamplesV = SamplesV + Vin;
                        delay (3);
                                                }
                        Vin=SamplesV/150;
                        //final mediere tensiune
                       
//Print the I on Serial monitor
                          //display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
                       
                            char I[32] ;
                            char V[32] ;
                            dtostrf(AcsValueF, 6, 2, I);
                            dtostrf(Vin, 6, 2, V);
                            Serial.print("I="); Serial.println(I);
                            Serial.print("V="); Serial.println(V);
                           

                            u8x8.setFont(u8x8_font_pxplusibmcga_r);
                            delay(10);

       /*                     if (Load = true){
                              u8x8.Inverse();
                              }*/
//Print I pe LCD
                            u8x8.draw2x2String(-2, 2, I); 
                            u8x8.draw2x2String(10,2," A");
                            delay(10);
//Print V pe LCD                   
                            //u8x8.Inverse();
                            u8x8.draw2x2String(-2, 4, V);
                            u8x8.draw2x2String(10,4," V");                           
                            delay(10);
                    }
}


I tooked 723 cause I measure 10amps, this doesn't change starting offset problem.the code rest the same imho.
I like uln/udn's but when they die, if you haven't put a socket, takes more longer to repair :)

last, don't take this like critics it's just my oppinion.

best regards,Ovidiu
 
The following users thanked this post: asokolsky

Offline perieanuo

  • Regular Contributor
  • *
  • Posts: 150
  • Country: fr
Re: Amp/Volt Meter with Fan Controller
« Reply #4 on: June 26, 2018, 03:40:59 pm »
I forgot, you can delete some part of the code, I also printed I and V on serial port output (in my power supply I have incorporated an ftdi 232 in order to reprogram the multimeter and took out the readings if I want.
regards,ovidiu
 

Offline Akarincoco

  • Newbie
  • Posts: 1
  • Country: th
Re: Amp/Volt Meter with Fan Controller
« Reply #5 on: June 26, 2018, 06:08:50 pm »
This review is the best.
 

Offline asokolsky

  • Newbie
  • Posts: 4
  • Country: us
Re: Amp/Volt Meter with Fan Controller
« Reply #6 on: June 27, 2018, 04:15:58 am »
Ovidiu,

Thanks for the code!  It will help me to get things started.
I hear you on ADS1115 being just a multiplexer.
And thank you for your advise to pulling the reset up.
Agreed on ULN being a culprit for maintenance in case it is burned and needs replacement.

I modified PCB so that I can start without ADS1115 and just using internal Arduino ADC.
My concern is that it takes 300ms for analog reading - you average over 100 samples with 3ms in between readings.  This alone makes cycle of V and A measurement 600ms.  I also want to measure temperature.  So the update rate of this meter is < 2/sec.  Not too responsive.  ADS1115 might be not only more precise but also much faster.

Cheers!
PS: Never read Romanian in comments yet!  I'm getting there!
Thanks again!
 

Offline perieanuo

  • Regular Contributor
  • *
  • Posts: 150
  • Country: fr
Re: Amp/Volt Meter with Fan Controller
« Reply #7 on: June 27, 2018, 03:52:38 pm »
You're welcome,
I'm looking forward to see upgrades.
Concerning temperature,it's anyway a slooooow process,you can measure every 10 secs :)
For speed I prefere bargraph style,I had a version like that.
Keep us on the loop and "bon courage"
Regards,ovidiu


Envoyé de mon iPad en utilisant Tapatalk
 

Offline perieanuo

  • Regular Contributor
  • *
  • Posts: 150
  • Country: fr
Re: Amp/Volt Meter with Fan Controller
« Reply #8 on: September 05, 2018, 09:01:08 pm »
Hi, any news?
I allready added to my variable power supply 2 cooler pwm triggered by temp sensing with thermistor then with transistor (simplier to attach with a m3 screw to radiator).surprised to see the transistor temp sensing is not too bad, enough precise for this app).
Thermistor was more precise and no need to calibrate but higher price for production, surprisingly, cause of mechanical contrains to attach the device to temp reading spot...


Envoyé de mon iPad en utilisant Tapatalk
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf