Amp/Volt Meter with Fan Controller - Page 1
Forum section: electronics / general

author: asokolsky
author_rank: Newbie
timestamp: June 25, 2018, 02:25:23 am
content: 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-ControlAlex

author: perieanuo
author_rank: Frequent Contributor
timestamp: June 25, 2018, 06:28:31 am
content: 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

author: asokolsky
author_rank: Newbie
timestamp: June 25, 2018, 07:36:04 pm
content: 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/2452and it refers to ACS711KEXLT-15AB-T which has 90 mV/A sensitivity.Replacing it with ACS723, e.g.https://www.sparkfun.com/products/13679which 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 ideaAgreed.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-0c20aa3afe5045e5a980d684715a4248https://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!

author: perieanuo
author_rank: Frequent Contributor
timestamp: June 26, 2018, 05:37:18 am
content: hi,here's the codeit'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 miniand 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:#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>#endifU8X8_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 pornirefloat AcsOffset=0.0,SamplesOffset=0.0,AvgAcsOffset=0.0,AcsValueOffset=0.0;for (int k = 0; k < 100; k++){ //Get 150 samplesAcsValueOffset = analogRead(A3); //Read current sensor valuesSamplesOffset = SamplesOffset + AcsValueOffset; //Add samples togetherdelay (3); // let ADC settle before next sample 3ms}AvgAcsOffset=SamplesOffset/100; //Taking Average of Samplesdouble 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 inputAcsValueOffset = (vccOffset - (AvgAcsOffset * (VccOffset / 1024.0)) )/0.100;Serial.print("I_Offset_boot=");Serial.println(AcsValueOffset);delay(10);/*// optional print I_Offsetu8x8.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 = { 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 creddelay(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);#elseADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);#endifdelay(2); // Wait for Vref to settleADCSRA |= _BV(ADSC); // Start conversionwhile (bit_is_set(ADCSRA,ADSC)); // measuringuint8_t low = ADCL; // must read ADCL first - it then locks ADCHuint8_t high = ADCH; // unlocks bothlong result = (high<<8) | low;result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000return result; // Vcc in millivolts}void loop() {Serial.begin(9600); //pt pb afisare I_Offset//corectie offset senzor curent ACS712,ruleaza o sg data la pornirefloat AcsOffset=0.0,SamplesOffset=0.0,AvgAcsOffset=0.0,AcsValueOffset=0.0;for (int k = 0; k < 100; k++){ //Get 100 samplesAcsValueOffset = analogRead(A3); //Read current sensor valuesSamplesOffset = SamplesOffset + AcsValueOffset; //Add samples togetherdelay (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 inputAcsValueOffset = (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 boardu8x8.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 Ifloat AcsValue=0.0,Samples=0.0,AvgAcs=0.0,AcsValueF=0.0;for (int x = 0; x < 150; x++){ //Get 150 samplesAcsValue = analogRead(A3); //Read current sensor valuesSamples = Samples + AcsValue; //Add samples togetherdelay (3); // let ADC settle before next sample 3ms}AvgAcs=Samples/150; //Taking Average of Samplesdouble 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 inputAcsValueF = (vcc - (AvgAcs * (Vcc / 1024.0)) )/0.100;AcsValueF = AcsValueF - AcsValueOffset; //corectie offset senzor curent ACS712//final mediere curentAcsValueF = abs(AcsValueF); //elimin semn - masor doar curent pozitiv/*//curent ne-mediatfloat 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 inputAcsValueF = (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.28k_divider= (Rup+Rdown) / Rdown ;float k = 1; //Divizor 2K2 JOS/ 10K SUS//ERAk= 5* k_divider;k = k * k_calibrare;//mediere tensiunefloat 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 bitiSamplesV = 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 ;char V ;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 LCDu8x8.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 repairlast, don't take this like critics it's just my oppinion.best regards,Ovidiu

author: perieanuo
author_rank: Frequent Contributor
timestamp: June 26, 2018, 05:40:59 am
content: 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

author: Akarincoco
author_rank: Newbie
timestamp: June 26, 2018, 08:08:50 am
content: This review is the best.

author: asokolsky
author_rank: Newbie
timestamp: June 26, 2018, 06:15:58 pm
content: 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!

author: perieanuo
author_rank: Frequent Contributor
timestamp: June 27, 2018, 05:52:38 am
content: You're welcome,I'm looking forward to see upgrades.Concerning temperature,it's anyway a slooooow process,you can measure every 10 secsFor speed I prefere bargraph style,I had a version like that.Keep us on the loop and "bon courage"Regards,ovidiuEnvoyé de mon iPad en utilisant Tapatalk

author: perieanuo
author_rank: Frequent Contributor
timestamp: September 05, 2018, 11:01:08 am
content: 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

author: wasyoungonce
author_rank: Frequent Contributor
timestamp: November 27, 2018, 10:20:21 pm
content: Very nice...missed this before but would be great for DIY PSUs.

author: fchk
author_rank: Frequent Contributor
timestamp: January 03, 2019, 09:17:00 pm
content: Quote from: asokolsky on June 25, 2018, 02:25:23 amWhat are the planned specs?- voltage range?- current range?- AC/DC- negative voltages?depending on your target specs this could be interesting:http://www.ti.com/product/ina226This is a chip that measures voltage, current, and watts. Quite space-saving and meant as supervisor circuit for server boards etc. TI has got a whole bunch of these.PS:For fan control please read:https://www.glkinst.com/cables/cable_pics/4_Wire_PWM_Spec.pdfThis is the official Intel specification how to control 4-pin fans. Might be helpful.