Closed imk2021 closed 2 years ago
Thanks for reporting the issue.
This is sort of a known problem as the complexity of the signal changes with the dimmer setting as you stated. I assume the BRYMEN (I have one too, they are great) makes more samples to determine the crest factor (form factor).
Could you do the following experiment:
If your dimmer is under program control - I see dimmer.setPower(n) - it might be possible to derive a function to calculate the crest factor. The crest factor can be approached by the area under the sine function times some constant:
integral sin(x) => 1 - cos(x) - (from my head)
The setPower() parameter n goes from 0..maxN which equals x going from 0 .. PI (radians)
So the formula for the crest factor will probably look something like:
const float cf = 1.0/ (2 * sqrt(2)); // this value is my best guess
float ff = (1 - cos( (n * PI) / maxN)) * cf;
PS, email is in the json file
(some more thoughts)
I am afraid your ACS712 library produces very inconsistent results.
The wave form is quite complex indeed, for this kind of wave forms I do not expect the library to be smart enough.
looking at the point of the spike in the signal I assume it is leading edge phase control. https://www.dmlights.com/help/lighting/different-methods-dimming/
Problem is that the form factor changes per setting of the dimmer.
Tip: to make a better picture of the scope you better take some distance, so the autofocus can do its job. Normally that allows to cut the important part with enough resolution afterwards.
Another way to determine the RMS current should be sampling. I have no hardware setup near so please test this function and compare to your BRYMEN. If the function works I can add it to the library.
// PARAM TYPICAL VALUE
// frequency = 50.0
// mVperStep = 5000.0 / 1023.0 (Assume Arduino UNO ADC) = 4.887586
// mVperAmpere = 100.0
// analogPin = A0
float RMS_by_sampling(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin)
{
uint16_t midpoint = 511; // UNO midpoint.
uint16_t period = round(1000000UL / frequency);
float AmpPerStep = mVperStep / mVperAmpere;
uint16_t samples = 0;
float sumSquared = 0;
uint32_t start = micros();
while (micros() - start < period)
{
samples++;
float current = (analogRead(analogPin) - midpoint) * AmpPerStep;
sumSquared += (current * current);
}
// Serial.print(samples);
// Serial.print("\t");
float RMS = sqrt(sumSquared / samples);
return RMS;
}
(compiles)
Hello Rob and many thanks for your replies.
So here are the test results for your first github message.
Attached are some ACS721 output pin scope images, without any electronic filter:
ZeroLoadNoise 100W-Not-Dimmed BRYMEN 0.435A ACS712 Library Output , Mean of Ten calls to ACS.mA_AC() 0.353A
200w-Load-Dimmer-25% BRYMEN 0.472A ACS712 Library Output , Mean of Ten calls to ACS.mA_AC() 0.804A 200w-Load-Dimmer-50% BRYMEN 0.705A ACS712 Library Output , Mean of Ten calls to ACS.mA_AC() 0.683A 200w-Load-Dimmer-75% BRYMEN 0.815A ACS712 Library Output , Mean of Ten calls to ACS.mA_AC() 0.704A 200w-Load-Dimmer-100% BRYMEN 0.536A ACS712 Library Output , Mean of Ten calls to ACS.mA_AC() 0.336A
As can be seen dimmed 25%, 50%, 75% look expected waveform. But something goes wrong I think in the dimmer library as only half power and the lamps are not full brightness,
I will do more testing tomorrow, I hope this help Ian
The mA-AC() works on the peaks of the signal during one period. As the peaks are not representative for the (distorted)e signal the math with the crest factor fails. So definitely not OK.
It surprises me that the DMM measures its highest current somewhere around 75% and not at 100%. Does the voltage drop? Do you have a datasheet / docs /link of the dimmer?
Hello Rob,
So i had an hour spare this evening to try the RMS_by_sampling function you said i might try. Unfortunately your version does not seem to work, as it seems to returns immediately rather than run for many sample, maybe you meant mills and not micros for the timing. So i did a quick hack at it and replaced the timer function with a simple FOR 10000 loop, this seems to produce some results. However the RMS output is off by about a factor of 40 or so, inasmuch as simple 100w lamp load BRYMEN's says 0.435mA and the LCD displays 17.99 or so. It is also interesting to note that sometimes when turning the load on the LCD display only 0.02 or so... This maybe a loose connection on my rig, or a power spike to the Nano....need more testing
Thought you might be interested please see capture of sketch below, all the best Ian
// // FILE: ROB_RMS_TEST_1.ino // AUTHOR: Ian Knight, Rob Tillaart // PURPOSE: To test the Return RMS Function // DATE: 2022-08-16
voidloop() { // set the cursor to column 0, line 1 (note: line 1 is the second row, since counting begins with 0): //TheRMS = RMS_by_sampling( 50.0 , 4.887586 , 100.0 , A0 ); TheRMS = RMS_by_sampling( 50.0, 4.887586, 100.0, ACS712_ANALOG_PIN ); DisplayToLCDTotalCurrent(); MaxmA = analogRead( ADJUSTABLE_MAX_CURRENT_ANALOG_PIN ); MaxmA = map( MaxmA , 0, 1023, 0, 20000); // Map ADC 0->1023 to 0->20000 mA DisplayToLCDMaxCurrent(); }
floatRMS_by_sampling( floatfrequency, floatmVperStep, floatmVperAmpere, uint8_tanalogPin) { uint16_tmidpoint = 511; uint16_tperiod = round(1000000UL/ frequency); float AmpPerStep = mVperStep / mVperAmpere; uint16_tsamples = 0; float sumSquared = 0; uint32_tstart = micros(); while( micros() - start < period ) { samples++; floatcurrent = (analogRead(analogPin) - midpoint) AmpPerStep; sumSquared += (current current); } floatRMS = sqrt(sumSquared) / samples; //return( round(RMS) ); return( RMS ); }
voidDisplayToLCDMaxCurrent( void) { lcd.setCursor(0, 0);// Col, row lcd.print(" ");// Clear Line lcd.setCursor(0, 0); lcd.print( MaxmA ); // print the System Maximum mA } // -- END OF FILE --
Thanks for testing, So I time to 'disect' that RMS code ... If the error is a constant factor it is easy to patch.
Think I need some hardware to build a test setup. I will look if I have a spare sensor somewhere.
saw one error in my code - already updated above -
Was float RMS = sqrt(sumSquared)/ samples;
should be
float RMS = sqrt(sumSquared / samples); // the () should be around the whole expression.
Dividing by samples after doing the square root makes the outcome at least sqrt(samples) too small.
Can you retry? I'll going to check if I have some hardware today
BRYMEN's says 0.435mA ...
I assume a 100W lamp uses 435 mA 😁
Morning Rob and many thanks for the support.
I have busy day ahead so i am unable to do more testing until this evening. However i implemented your update to
float RMS = sqrt(sumSquared / samples);
into my FOR 10000 sample function as can be seen below.
Output for 100W 240V resistive load is BRYMEN 0.435A The function returns 2150.5 not sure if A or mA
I should be back about 1900 today to do further testing, have a good day Ian
floatRMS_by_sampling( floatfrequency, floatmVperStep, floatmVperAmpere, uint8_tanalogPin) { uint16_tmidpoint = 511; //uint16_t period = round(1000000UL / frequency); float AmpPerStep = mVperStep / mVperAmpere; uint16_tsamples = 0; float sumSquared = 0; ///uint32_t start = micros(); for( inti = 0; i < 10000; i++ ) { samples++; floatcurrent = (float)( analogRead( analogPin ) - midpoint ) AmpPerStep; sumSquared += (current current); } //float RMS = sqrt(sumSquared) / samples; floatRMS = sqrt(sumSquared / samples); return( RMS ); }
Do you have a datasheet / docs /link of the dimmer?
Hello Rob,
Please find below link to the 8A dimmer i am currently testing with. However the testing I have done with the RMS_by_sampling() function have all been done with a NONE dimmed 100W load. Although the dimmer module is still wired to the NANO but is not software enabled.
Am home again now and able to do more testing if you wish, all best Ian
Thanks for the link, I had a quick look at the library for it - https://github.com/RobotDynOfficial/RBDDimmer and it looks pretty dedicated (timer interrupts etc) per platform.
Did not make progress today (too much "non maskable interrupts") so I have to catch up tasks. I'll be online around 21:00 GMT again, maybe earlier.
Minor changes in the RMS code, added some print
// PARAM TYPICAL VALUE
// frequency = 50.0
// mVperStep = 5000.0 / 1023.0 (Assume Arduino UNO ADC) = 4.887586
// mVperAmpere = 100.0
// analogPin = A0
float RMS_by_sampling(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin)
{
uint16_t midpoint = 511; // UNO midpoint.
uint32_t period = round(1000000UL / frequency); // should be ~20k micros
Serial.println(period);
float AmpPerStep = mVperStep / mVperAmpere; // should be ~0.048875 Ampere per step.
Serial.println(AmpPerStep, 5);
uint32_t samples = 0;
float sumSquared = 0;
uint32_t start = micros();
while (micros() - start < period)
{
samples++;
float current = (analogRead(analogPin) - midpoint) * AmpPerStep; // unit = Amperes.
sumSquared += (current * current); // unit = Ampere squared.
}
float RMS = sqrt(sumSquared / samples); // unit = Ampere.
Serial.println(RMS, 5);
return RMS; // current = Amperes.
}
If you run this with the 100Watt lamp 100W / 230 V = 0.435 Ampere, what does it return?
Can you do the test with a load of ~1000 Watt e.g. an iron? 1000W/230V = 4.4 Ampere
A problem with a load of 100 W could be that the point2point (max signal - min signal) is only 25 steps. So the peak above the midpoint is only 12 or 13 steps. (Ampere per step = 5000/1023/100 = 0.048875. As noise can easily be a 2-5 steps this is a substantial part (30%) of the peak => so even more of the non peak part.
A 1000 W load should be less affected by the noise.
from ma_AC()
float mA = (500.0 * point2point) * _mVperStep * _formFactor / _mVperAmpere;
500 25 4.8875 / sqrt(2) / 100 = 432 mA (that is what BRYMEN measured)
Hello Rob,
Quick note re RobotDyn Library interrupts/timers etc.
During my early testing couple of weeks ago, I was doing a long Serial.print message in loop every second. This caused the dimmer output to dim at the same same rate as the Serial.print.
I Think the serial out interrupt was interfering with the Dimmer Library interrupts/timers. This I will build a proper rig for when i get a moment and test thoroughly as is potential problem.
I shall do other testing for you in next hour or so and send to you, Ian
Rob,
Tested at 9600 bps serial, it is interesting to note that the serial output is very fast, implying that is doing not do many samples in RMS_by_sampling.
Also note micro() wraps after a few minutes, so may produce inconstant results, maybe us mills()
Output from Serial Print Version of RMS_by_sampling() without any load: Brymen 0.007A
Serial Output from Arduino IDE V2.0.0 RC9.2 with time stamp:
21:58:23.702 -> 0.04888 21:58:23.702 -> 0.36488 21:58:23.733 -> 20000 21:58:23.733 -> 0.04888 21:58:23.733 -> 0.36870 21:58:23.765 -> 20000 21:58:23.765 -> 0.04888 21:58:23.765 -> 0.36849 21:58:23.807 -> 20000 21:58:23.807 -> 0.04888 21:58:23.807 -> 0.36226 21:58:23.842 -> 20000 21:58:23.842 -> 0.04888 21:58:23.842 -> 0.36585 21:58:23.877 -> 20000 21:58:23.877 -> 0.04888 21:58:23.877 -> 0.36594 21:58:23.913 -> 20000 21:58:23.913 -> 0.04888 21:58:23.913 -> 0.36660 21:58:23.947 -> 20000 21:58:23.947 -> 0.04888 21:58:23.947 -> 0.36245 21:58:23.982 -> 20000
Output from Serial Print Version of RMS_by_sampling() with 100W load at 237V:
Brymen 0.436A
Serial Output from Arduino IDE V2.0.0 RC9.2 with time stamp:
22:3:33.409 -> 1525.90014 22:3:33.442 -> 20000 22:3:33.442 -> 0.04888 22:3:33.442 -> 1531.34667 22:3:33.483 -> 20000 22:3:33.483 -> 0.04888 22:3:33.483 -> 1501.86999 22:3:33.518 -> 20000 22:3:33.518 -> 0.04888 22:3:33.518 -> 1477.44860 22:3:33.555 -> 20000 22:3:33.555 -> 0.04888 22:3:33.555 -> 1452.61437 22:3:33.591 -> 20000 22:3:33.591 -> 0.04888 22:3:33.591 -> 1525.90161 22:3:33.627 -> 20000 22:3:33.627 -> 0.04888 22:3:33.627 -> 1531.33801 22:3:33.662 -> 20000 22:3:33.662 -> 0.04888 22:3:33.662 -> 1501.87451 22:3:33.699 -> 20000 22:3:33.699 -> 0.04888 22:3:33.699 -> 1477.44470 22:3:33.735 -> 20000 22:3:33.735 -> 0.04888 22:3:33.735 -> 1477.44641 22:3:33.770 -> 20000 22:3:33.770 -> 0.04888 22:3:33.770 -> 1477.44799 22:3:33.808 -> 20000 22:3:33.808 -> 0.04888 22:3:33.808 -> 1477.44799 22:3:33.844 -> 20000 22:3:33.844 -> 0.04888 22:3:33.844 -> 1452.61511 22:3:33.880 -> 20000 22:3:33.880 -> 0.04888 22:3:33.880 -> 1477.45007
Hope that helps Ian
Sure this helps, at least two parameters are as expected.
The micros() does wrap every 10 minutes or so. As the code uses subtraction in the comparison it works.
Serial output is handled in the background, and yes it affects the analogRead() Lets count the number of samples. (load 100W for now) to find out.
Can you verify that the midpoint = 2.5V ?
void setup()
{
Serial.begin(9600);
}
void loop()
{
float amps = RMS_by_sampling(50, 4.887586, 100, A0);
Serial.println(amps);
Serial.println();
delay(1000);
}
// PARAM TYPICAL VALUE
// frequency = 50.0
// mVperStep = 5000.0 / 1023.0 (Assume Arduino UNO ADC) = 4.887586
// mVperAmpere = 100.0
// analogPin = A0
float RMS_by_sampling(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin)
{
uint16_t midpoint = 511; // UNO midpoint.
uint32_t period = round(1000000UL / frequency); // should be ~20k micros
float AmpPerStep = mVperStep / mVperAmpere; // should be ~0.048875 Ampere per step.
uint32_t samples = 0;
float sumSquared = 0;
uint32_t start = micros();
while (micros() - start < period)
{
samples++;
float current = (analogRead(analogPin) - midpoint) * AmpPerStep; // unit = Amperes.
sumSquared += (current * current); // unit = Ampere squared.
}
float RMS = sqrt(sumSquared / samples); // unit = Ampere.
Serial.println(samples);
Serial.println(RMS, 5);
return RMS; // current = Amperes.
}
Note to myself:
There is an optimization, the * AmpPerStep;
in the loop can be outside the loop.
Would save a float multiply every loop, and adds 2 float multiplies instead.
Hello Rob, Please find test result for your mini app ROB_RMS_TEST_2.ino
5V Uno supply from USB 4.68v ACS721 No load midpoint 2.35v
No load BryMen 0.006A, Your app results below
15:35:02.373 -> 0.49 15:35:02.373 -> 15:35:03.402 -> 139 15:35:03.402 -> 0.49355 15:35:03.402 -> 0.49 15:35:03.402 -> 15:35:04.418 -> 139 15:35:04.418 -> 0.49249 15:35:04.418 -> 0.49 15:35:04.418 -> 15:35:05.447 -> 139 15:35:05.447 -> 0.49468 15:35:05.447 -> 0.49 15:35:05.447 -> 15:35:06.461 -> 139 15:35:06.461 -> 0.49259 15:35:06.461 -> 0.49 15:35:06.461 -> 15:35:07.475 -> 139 15:35:07.475 -> 0.49369 15:35:07.475 -> 0.49 15:35:07.475 -> 15:35:08.523 -> 139 15:35:08.523 -> 0.49046 15:35:08.523 -> 0.49 15:35:08.523 -> 15:35:09.539 -> 139 15:35:09.539 -> 0.49319 15:35:09.539 -> 0.49 15:35:09.539 -> 15:35:10.537 -> 139 15:35:10.537 -> 0.49216 15:35:10.537 -> 0.49 15:35:10.537 -> 15:35:11.539 -> 139 15:35:11.539 -> 0.49611 15:35:11.539 -> 0.50 15:35:11.539 ->
100W load BryMen 0.431A, Your app results below
15:39:40.996 -> 1912.74 15:39:40.996 -> 15:39:42.040 -> 143 15:39:42.040 -> 1949.89526 15:39:42.040 -> 1949.90 15:39:42.040 -> 15:39:43.071 -> 143 15:39:43.071 -> 1949.89147 15:39:43.071 -> 1949.89 15:39:43.071 -> 15:39:44.086 -> 143 15:39:44.086 -> 1931.40795 15:39:44.086 -> 1931.41 15:39:44.086 -> 15:39:45.115 -> 144 15:39:45.115 -> 1943.10546 15:39:45.115 -> 1943.11 15:39:45.115 -> 15:39:46.129 -> 143 15:39:46.129 -> 1949.89074 15:39:46.129 -> 1949.89 15:39:46.129 -> 15:39:47.121 -> 142 15:39:47.121 -> 1919.46875 15:39:47.121 -> 1919.47 15:39:47.121 -> 15:39:48.164 -> 142 15:39:48.164 -> 1938.19055 15:39:48.164 -> 1938.19 15:39:48.164 -> 15:39:49.197 -> 142 15:39:49.197 -> 1956.74804 15:39:49.197 -> 1956.75 15:39:49.197 -> 15:39:50.210 -> 143 15:39:50.210 -> 1968.20080 15:39:50.210 -> 1968.20 15:39:50.210 ->
Very insightful! thanks a lot
ACS721 No load midpoint 2.35v
Assumed 2.5V so lets adapt the midpoint in code 2.35 / 5.00 * 1023 = 480
5V Uno supply from USB 4.68v
Assumed 5V so lets adapt too 4680 / 1023 = 4,57478 mVperstep.
void setup()
{
Serial.begin(9600);
}
void loop()
{
float amps = RMS_by_sampling(50, 4.57478, 100, A0);
Serial.println(amps);
Serial.println();
delay(1000);
}
// PARAM TYPICAL VALUE
// frequency = 50.0
// mVperStep = 5000.0 / 1023.0 (Assume Arduino UNO ADC) = 4.887586
// mVperAmpere = 100.0
// analogPin = A0
float RMS_by_sampling(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin)
{
uint16_t midpoint = 480; // UNO midpoint.
uint32_t period = round(1000000UL / frequency); // should be ~20k micros
float AmpPerStep = mVperStep / mVperAmpere; // should be ~0.048875 Ampere per step.
uint32_t samples = 0;
float sumSquared = 0;
uint32_t start = micros();
while (micros() - start < period)
{
samples++;
float current = (analogRead(analogPin) - midpoint) * AmpPerStep; // unit = Amperes.
sumSquared += (current * current); // unit = Ampere squared.
}
float RMS = sqrt(sumSquared / samples); // unit = Ampere.
Serial.println(samples);
return RMS; // current = Amperes.
}
Give it a try, should be closer to the BRYMEN now.
Note: As the midpoint was 31 steps off (511-480) , half of the measurements - and squared - was way too high. So a call to autoMidPoint is mandatory ...
optimized version, replaced a multiplication for every measurement in the loop with one outside the loop
float RMS_by_sampling(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin)
{
uint16_t midpoint = 480; // UNO midpoint.
uint32_t period = round(1000000UL / frequency);
float AmpPerStep = mVperStep / mVperAmpere;
uint16_t samples = 0;
float sumSquared = 0;
uint32_t start = micros();
while (micros() - start < period)
{
samples++;
uint32_t current = analogRead(analogPin) - midpoint;
sumSquared += (current * current);
}
float RMS = sqrt(sumSquared / samples) * AmpPerStep;
Serial.println(samples);
return RMS;
}
Hello Rob, Please find test result for your mini app ROB_RMS_TEST_3.ino
100W load BryMen 0.433A, Your app results below
18:10:19.585 -> 140 18:10:19.585 -> 1.87211 18:10:19.585 -> 1.87 18:10:19.585 -> 18:10:20.599 -> 140 18:10:20.599 -> 1.86943 18:10:20.599 -> 1.87 18:10:20.599 -> 18:10:21.617 -> 140 18:10:21.617 -> 1.86537 18:10:21.617 -> 1.87 18:10:21.617 -> 18:10:22.615 -> 140 18:10:22.616 -> 1.86387 18:10:22.616 -> 1.86 18:10:22.616 -> 18:10:23.663 -> 140 18:10:23.663 -> 1.86361 18:10:23.663 -> 1.86 18:10:23.663 -> 18:10:24.697 -> 141 18:10:24.697 -> 1.86070 18:10:24.697 -> 1.86 18:10:24.697 -> 18:10:25.718 -> 141 18:10:25.718 -> 1.86190 18:10:25.718 -> 1.86 18:10:25.718 ->
Just go your up date this i'll test in couple of minutes and call it ROB_RMS_TEST_4.ino Ian
Hello Rob, Please find test result for your mini app ROB_RMS_TEST_4.ino
100W load BryMen 0.434A, Your app results below
18:22:08.664 -> 1.85 18:22:08.664 -> 18:22:09.678 -> 157 18:22:09.678 -> 1.85 18:22:09.678 -> 18:22:10.695 -> 157 18:22:10.695 -> 1.85 18:22:10.695 -> 18:22:11.730 -> 157 18:22:11.730 -> 1.86 18:22:11.730 -> 18:22:12.727 -> 157 18:22:12.727 -> 1.85 18:22:12.727 -> 18:22:13.770 -> 157 18:22:13.770 -> 1.86 18:22:13.770 -> 18:22:14.786 -> 157 18:22:14.786 -> 1.86 18:22:14.786 -> 18:22:15.783 -> 157 18:22:15.783 -> 1.85 18:22:15.783 -> 18:22:16.830 -> 157 18:22:16.830 -> 1.86
Ian
So number of samples increased and still no substantial improvement in the measurement.
Can you run without load? to see if the zero point is improved?
think it is time to get the raw data, as raw as possible.
Should give one period of raw data.
uint16_t samp[250];
void setup()
{
Serial.begin(9600);
Serial.println();
uint16_t samples = 0;
uint32_t start = micros();
while (micros() - start < 20000)
{
samp[samples] = analogRead(A0);
samples++;
delayMicroseconds(28); // simulate math so we get ~145 samples.
}
Serial.print("samples: ");
Serial.println(samples);
for (int i = 0; i < samples; i++)
{
if ((i % 10) == 0) Serial.println();
Serial.print(samp[i]);
Serial.print("\t");
}
Serial.println("\n\ndone...");
}
void loop()
{
}
Rob please results for ROB_RMS_TEST_RAW_DATA_1.ino
Zero Load
19:30:33.115 -> 19:30:33.180 -> samples: 146 19:30:33.180 -> 19:30:33.180 -> 520 520 520 521 520 519 519 520 520 520 19:30:33.213 -> 520 520 521 520 519 520 520 520 520 519 19:30:33.280 -> 520 519 520 520 520 519 519 520 520 520 19:30:33.313 -> 520 520 520 520 519 520 519 520 520 519 19:30:33.346 -> 519 520 521 519 519 520 519 520 519 520 19:30:33.413 -> 520 520 520 519 520 519 519 520 520 520 19:30:33.445 -> 519 520 520 520 520 520 521 520 520 520 19:30:33.479 -> 520 520 519 520 520 520 520 520 520 520 19:30:33.546 -> 520 519 520 520 520 520 520 519 519 519 19:30:33.579 -> 519 519 520 519 521 520 519 519 520 520 19:30:33.612 -> 520 520 520 520 520 520 520 520 520 519 19:30:33.645 -> 521 520 520 520 520 520 520 520 520 520 19:30:33.712 -> 520 520 520 520 520 520 520 520 519 519 19:30:33.745 -> 520 520 520 520 520 520 520 519 520 519 19:30:33.779 -> 520 520 520 519 520 520 19:30:33.814 -> 19:30:33.814 -> done...
Brymen 0.434A load
19:33:45.882 -> 19:33:45.914 -> samples: 146 19:33:45.914 -> 19:33:45.914 -> 535 535 534 534 534 532 532 532 532 532 19:33:45.962 -> 531 530 530 529 529 529 528 528 527 527 19:33:46.040 -> 526 526 525 525 524 524 522 522 522 521 19:33:46.074 -> 522 520 520 521 519 518 518 518 517 517 19:33:46.107 -> 516 516 515 515 515 515 515 514 515 514 19:33:46.173 -> 514 514 513 514 514 513 514 514 514 514 19:33:46.207 -> 513 513 513 513 514 513 514 514 515 516 19:33:46.240 -> 515 516 516 516 517 517 517 517 519 519 19:33:46.306 -> 518 520 519 520 520 520 522 522 522 523 19:33:46.340 -> 524 524 524 525 526 526 527 527 527 528 19:33:46.372 -> 528 529 529 530 530 532 532 533 532 533 19:33:46.406 -> 533 533 534 535 534 535 535 536 536 537 19:33:46.473 -> 536 536 536 537 537 537 536 537 537 538 19:33:46.506 -> 536 537 536 537 538 537 537 538 537 538 19:33:46.540 -> 537 537 536 536 535 536 19:33:46.584 -> 19:33:46.584 -> done...
Hope that help Ian
The first raw measurement shows that the midpoint is about 520 now. ~ that is about 2.54 volt. Compared to the 2.35 V you mentioned earlier this is ~20% fluctuation
Rob your:
The first raw measurement shows that the midpoint is about 520 now. ~ that is about 2.54 volt. Compared to the 2.35 V you mentioned earlier this is ~20% fluctuation
The mid measurement i gave was Brymen DC volt at zero load on output pin of ACS712
The data points are from ADC output, not sure why they are different.
Ian
Put the 146 measurements (2nd run) in Excel.
0.417 is pretty close to the BRYMEN value, (given the zero level is probably fluctuating)
Can you post your schematic, exactly how you connected the ACS712 to the Processor?
The mid measurement i gave was Brymen DC volt at zero load on output pin of ACS712 The data points are from ADC output, not sure why they are different.
That's what we need to find out.
Can you post your schematic, exactly how you connected the ACS712 to the Processor?
Most important thing is that the GND of the ACS712 and the GND of the Processor are connected. This forces a common reference for all voltages.
Second, the power supply of both the ACS712 and the Processor should be stable 5V even under a load. The ACS712 needs it to generate 2.5V as midpoint, and the Processor needs it as a reference for its ADC.
I'm going to implement a 0.2.8 version that includes this sampling function as it has serious added value for non trivial signals. It might replace the mA_AC() in time as the form factor is obsolete.
Hello Rob,
I think the present approach of trying to determine the RMS current from a single cycle is a bit optimistic. My reasoning for this is two fold, there is always going to be on the mains noise from sources we have no control over like next doors fridge etc etc. Two during our test I notice that the BRYMEN does not give and instant value of RMS current. As it takes 2, 3 or 4 seconds from the load being switched on to present a steady value, likewise when the load is switched off it take as long as 10 seconds to reach zero.
Hence i think we need a function where one of the parameters is the number of cycles to sample and see how that test rather than chase single cycle noise.
What you think? Ian
Good thoughts!
I have to look at it from every possible use case , the perspective of a library developer.
The library provides one cycle which is the minimum. A user can call that function in a loop, adjust midpoint every 7 iterations whatever meets his needs. The user can average the values, ignore outliers etc. So many scenario's you cannot parameterize the function to meet all that. So functions should be seen as the building block of a solution.
On the other hand the quality of the software solution can only compensate hardware limitations to some extend. So if there is an electric problem with midpoint the lib cant solve, multiple samples wont fix it.
Rob
Re multi calls to your library. Problem is with multiple calls is the call setup (stack pushing etc) means you will have a mini dead band from call to call.
I Still think it better to get in mA_AC() for n cycles, would be interesting to see the difference between: mA_AC() and mA_AC_Mean_Cycles()
Ian
Implement and test your assumption. That is the only way to proof that the parameter add value.
I expect that the overhead of a function call is maybe 20x less than a single analogRead(). So you wont notice the difference, but I can be wrong
this could be the code
float RMS_cycles(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin, uint16_t times)
{
uint16_t midpoint = 511; // UNO midpoint.
uint32_t period = round(1000000UL / frequency);
float AmpPerStep = mVperStep / mVperAmpere;
if (times < 1) times = 1;
float average = 0;
for (uint16_t i = 0; i< times; i++)
{
uint16_t samples = 0;
float sumSquared = 0;
uint32_t start = micros();
while (micros() - start < period)
{
samples++;
uint32_t current = analogRead(analogPin) - midpoint;
sumSquared += (current * current);
}
float RMS = sqrt(sumSquared / samples) * AmpPerStep;
average += RMS;
}
return average/times;
}
Another option could be a parameter to add the number of seconds the sampling should take.
float RMS_seconds(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin, uint8_t seconds)
{
uint16_t midpoint = 511; // UNO midpoint.
uint32_t period = seconds * 1000000UL;
float AmpPerStep = mVperStep / mVperAmpere;
uint32_t samples = 0;
float sumSquared = 0;
uint32_t start = micros();
while (micros() - start < period)
{
samples++;
uint32_t current = analogRead(analogPin) - midpoint;
sumSquared += (current * current);
}
float RMS = sqrt(sumSquared / samples) * AmpPerStep;
Serial.println(samples);
return RMS
}
Hello Rob,
I'll will give both versions a test tonight for you on 100W, 200W and 1kW loads this evening and let you know.
Ian
Created a develop branch 0.2.8 with
Hello Rob, sorry but things domestic busy so only limited testing this evening, will do more tomorrow.
See below sketch Ian
TheRMS = RMS_Cycles( 50.0, 4.887586, 100.0, ACS712_ANALOG_PIN , 50);
No Load BRYMEN 0.01A LCD RMS 0.1 100W Load BRYMEN 0.433A LCD RMS Jitter 2048.9 to 2062.0 Think jitter is pretty good
TheRMS = RMS_Duration( 50.0, 4.887586, 100.0, ACS712_ANALOG_PIN , 1);
No Load BRYMEN 0.01A LCD RMS 0.12 100W Load BRYMEN 0.433A LCD RMS Jitter 2111.0 to 2128.6 Think jitter is pretty good
I think I have a questionable connection from ACS712 to Nano, will look into this in morning. Question what is you plan to get present RMS output into mA's PS What you think of Arduino IDE V2, I think is amazing :-)
// // FILE: ROB_RMS_TEST_SAMPLE_SET_1.ino // AUTHOR: Ian Knight, Rob Tillaart // PURPOSE: To test the Return RMS Function // DATE: 2022-08-19
voidDisplayToLCDMaxCurrent( void) { lcd.setCursor(0, 0);// Col, row lcd.print(" ");// Clear Line lcd.setCursor(0, 0); lcd.print( MaxmA ); // print the System Maximum mA } // -- END OF FILE --
Question what is you plan to get present RMS output into mA's
The sampling function will return float mA in 0.2.8
In 0.3.0 I planned to redo all return types. mA_AC() and mA_DC() will also return float. Especially for the ASC712-5A this gives a bit more accuracy for low currents, think ESP32 with 12 bits ADC Furthermore I intent to investigate the use of external ADC's e.g ADS1115 ADC which is 16 bit. This gives a resolution below 1 mA.
Don't know if it will be a new class ACS712_EXT or that it can be build in and add a function to overwrite the analogRead().
PS What you think of Arduino IDE V2, I think is amazing :-) Not used it yet, I'm still on 1.8.19
Morning Rob, as promised more test data
TheRMS = RMS_Cycles( 50.0, 4.887586, 100.0, ACS712_ANALOG_PIN , 50);
No Load BRYMEN 0.004A LCD RMS 0.25
100W Load BRYMEN 0.43A LCD RMS Jitter 2130.5 to 2135.5 200W Load BRYMEN 0.824A LCD RMS Jitter 2198.5 to 2201.5 1000W Load BRYMEN 4.505A LCD RMS Jitter 2252 to 2254
TheRMS = RMS_Duration( 50.0, 4.887586, 100.0, ACS712_ANALOG_PIN , 1);
100W Load BRYMEN 0.43A LCD RMS Jitter 2175 to 2186 200W Load BRYMEN 0.824A LCD RMS Jitter 2217 to 2223 1000W Load BRYMEN 4.505A LCD RMS Jitter 2251 to 2256
Note Output of ACS712 monitored on scope as follows: 100W PP 140mV to 168mV, RMS 40.9 mV 200W PP 240mV to 256mV, RMS 76.5 mV 300W PP 352mV to 368mV, RMS 116.2 mV 1000W PP 1.2V to 368mV, RMS 421.5 mV See Image
Am about today if more testing required Ian
The BRYMEN measurements look all consistent with each other.
The RMS scope measurements also look consistent, although the RMS measured by scope is ~10% too low.
100 Watt => 40.9 mV RMS with 100mVperAmpere => 0.409 Ampere which is pretty close to the 0.43 200 Watt => 76.5 mV RMS with 100mVperAmpere => 0.765 Ampere which is pretty close to the 0.824 1000 Watt => 421 mV RMS with 100mVperAmpere => 4.21 Ampere which is pretty close to the 4.505
100W Load BRYMEN 0.43A LCD RMS Jitter 2175 to 2186
200W Load BRYMEN 0.824A LCD RMS Jitter 2217 to 2223
1000W Load BRYMEN 4.505A LCD RMS Jitter 2251 to 2256
The output on the LCD is remarkable close to each other while one should expect a factor 10 between 100W and 1000W. Can you verify you have the right analog port A0 ?
Good Afternoon Rob,
RE your: The output on the LCD is remarkable close to each other while one should expect a factor 10 between 100W and 1000W. Can you verify you have the right analog port A0 ?
Yes jumper wire goes from ACS712 Out to NANO A0 (Pin 14) then I plug another DuPont jump into scope prob. Only cheap scope but it does most jobs fairly well, although on the 1000W load i noticed that the sine seems to have a flat top. Sign of transformer at end of road is saturating and only summer am expecting blackouts this winter :-(
All best Ian
Cheap scopes are remarkable good and useful. I do a lot with an "el cheapo" JYE Tech DSO150 - I have two of those. 95% of the time it is just to confirm there is a signal and that it looks as expected.
Sign of transformer at end of road is saturating and only summer am expecting blackouts this winter :-(
Does not sound like most reliable infrastructure. Do you have backups in place? I would invest in a bunch of car batteries and some LED light infrastructure.
The Serial print is interrupt based => that disrupts the timing of the dimmer which uses a HWtimer interrupt.
The Serial print is interrupt based => that disrupts the timing of the dimmer which uses a HWtimer interrupt.
Yes that is the issue; one wonder why they didn't think serial out was an issue or didn't bother to test it Give that serial out must be one of the most used feature of Arduino.
Hello Rob I am having issues with the ACS712 library ver 0.2.7/6 when reading complex AC waveform and i am wondering if you want my full project details and waveform photos to investigate. Basically the load on the AC line that the ACS712 is monitoring has two loads: Load One is an old 100w incandescent lamp controlled via a simple switch. Load Two is an old 200w incandescent lamp controlled the RBDdimmer function.
Switching on load One gives a clean sine ACS712 output and your library produces very good results. Switching on load Two gives a switched sine ACS712 output and your library produces good but variable results depend on the dimmer.setPower( n ); power level.
Switching on load One and load Two produces a complex ACS712 waveform (Sine plus Dimmer Spike) and I am afraid your ACS712 library produces very inconsistent results. compared to the in series BRYMEN BM257 RMS meter I am using.
I have had a look on Github for your email to send you full info, scope screen shots and my code and project wire info but i can't seem to find it so i am wondering how to proceed.
All best Ian Knight PS Ignore the jitter in the image, this is my poor camera