3 phase serial-only incorrect voltage reading etc.

Hello,

I've got a couple of emonTx Shields connected to an Arduino Leonardo, and linked with a USB cable to a Linux box (which runs emonHub).

I've used

https://github.com/openenergymonitor/emonTxFirmware/tree/master/emonTxShield/Shield_CT1234_Voltage_SerialOnly

and got sensible looking numbers out.

 

 

So I then hacked on

https://github.com/openenergymonitor/emonTxFirmware/tree/master/emonTxShield/Shield_CT1234_3Phase_Voltage

a bit, and took out the radio tx parts (but adding back in a delay).

 

But can't seem to get very useful results (see below), and the contents of the voltage sample array look a bit broken.

Before I started trying to work out what's up with it, I was wondering if anyone was doing 3 phase with serial-only and/or a Leonardo (or similar)?  Unfortunately the box isn't where I am, so debugging is a bit tricky...

I can try another emonTxShield on an Uno here, but I only have to CTs, and no 3 phase supply to experiment with.

Cheers,

Tim.

 

Total Samples: 281 Power Samples: 267 Time: 233 Crossings: 22
-205.61 
-246.62 
-255.60 
-256.57 
-250.56 
-217.69 
-171.00 
-100.60 
-26.49 
33.38 
90.02 
221.68 
171.99 
99.59 
27.48 
-31.39 
-88.04 
-149.44 
Voltage: -0.04
 Current 1: -0.00 Power 1: 0.00 VA 1: 0.00 PF 1: 0.85
 Current 2: -0.00 Power 2: -0.00 VA 2: 0.00 PF 2: -0.26
 Current 3: -0.00 Power 3: 0.00 VA 3: 0.00 PF 3: 0.53

Total Samples: 281 Power Samples: 267 Time: 234 Crossings: 22
-193.99 
-240.03 
-255.00 
-256.97 
-253.95 
-225.05 
-185.30 
-119.82 
-44.64 
18.28 
75.98 
229.74 
186.99 
117.52 
45.34 
-16.60 
-73.30 
-132.77 
Voltage: 530.95
 Current 1: 1.78 Power 1: 796.06 VA 1: 946.52 PF 1: 0.84
 Current 2: 3.37 Power 2: -475.44 VA 2: 1789.61 PF 2: -0.27
 Current 3: 5.40 Power 3: 1485.20 VA 3: 2868.22 PF 3: 0.52

Total Samples: 279 Power Samples: 268 Time: 231 Crossings: 22
-225.07 
-253.05 
-256.03 
-256.00 
-237.05 
-204.23 
-146.64 
-72.35 
-2.34 
262.31 
240.35 
205.52 
144.94 
69.66 
1.65 
-55.13 
-112.67 
-173.97 
Voltage: 47.66
 Current 1: 0.16 Power 1: 6.45 VA 1: 7.61 PF 1: 0.85
 Current 2: 0.30 Power 2: -3.92 VA 2: 14.26 PF 2: -0.27
 Current 3: 0.49 Power 3: ovf VA 3: 23.51 PF 3: -216141504.00

Total Samples: 291 Power Samples: 266 Time: 242 Crossings: 22
-168.35 
-98.95 
-25.84 
278.33 
273.23 
241.27 
196.48 
125.97 
53.75 
-7.22 
-63.96 
-126.45 
-184.71 
-229.79 
-242.81 
-243.83 
-240.87 
-210.02 
Voltage: 854.52
 Current 1: 35.72 Power 1: 7486.85 VA 1: 30526.38 PF 1: 0.25
 Current 2: 35.75 Power 2: 3531.29 VA 2: 30549.89 PF 2: 0.12
 Current 3: 36.56 Power 3: 8737.51 VA 3: 31241.95 PF 3: 0.28

TimSmall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

The same sketch gives sensible voltage readings on an Uno, so must be the 3 phase code not liking the Leonardo...

Tim.

Total Samples: 297 Power Samples: 282 Time: 232 Crossings: 22
254.61 
254.59 
233.65 
181.92 
123.43 
55.20 
-10.75 
-64.49 
-122.00 
-147.65 
-79.33 
-11.29 
42.54 
103.13 
157.49 
211.64 
246.65 
253.64 
Voltage: 237.61
 Current 1: 0.10 Power 1: 1.05 VA 1: 24.88 PF 1: 0.04
 Current 2: 0.00 Power 2: 0.00 VA 2: 0.00 PF 2: nan
 Current 3: 0.00 Power 3: 0.00 VA 3: 0.00 PF 3: nan
dBC's picture

Re: 3 phase serial-only incorrect voltage reading etc.

I wonder if you might be suffering from the problem discussed in this thread:  http://openenergymonitor.org/emon/node/10089.   If you are, and you're not using the RF stuff, that could well be another useful clue.  Robert's last post there said he was off to investigate if it might be in JeeLib, but if you're not using that,  and your problem is the same, you may save him some effort.

TimSmall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

Here's a graph of the above set of samples, plus another couple from the Uno.  Computed voltage is in brackets in the key.  Uno 2 voltage is missing sorry, but I'm pretty sure it was about the same as Uno 3 (233 or so), and was taken a few minutes apart at a higher load time for this area vs. the Uno 1 samples which were from yesterday).

I haven't had time to look at the algorithm to see what it's trying to do, but the graphs basically look pretty funky to me, and I'd hope they're not an accurate representation of my mains voltage waveform (perhaps they're not intended to be tho)! :o)

Tim.

Robert Wall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

The waveforms don't look obviously wrong! Bear in mind that it's only necessary to record one sample more than 120° 240 ° so you will never have a complete cycle recorded.

[And I'm still trying to find time to track down that problem!]
When you wrote "...must be the 3 phase code not liking the Leonardo..." I stopped looking at your particular problem as I know nothing about the Arduino range, so I'd be most unlikely to be able to help you.

TimSmall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

If you suspect it's something related to memory allocation, then the differences between the Uno and Leonardo may be relevant.  The Leonardo uses the Atmel ATmega32u4 with built-in USB functionality.

As a result, when the sketch I'm using is complied for the Uno (which has a separate USB <-> serial chip), the code size is 9134 bytes.  The same sketch compiled for the Leonardo comes in at 11788 bytes.

I'd guess the difference is the USB serial code (or maybe some boot loader code or something) which the Arduino IDE is including.

I just modified the sketch to allocate a static string (like this char *spacewaster = "blahblahblah [...] blah";) to push the Uno code size up to the same Leonardo.  The static string isn't referenced anywhere else in the code.

The Uno version now outputs garbage and sometimes chunks of the static string instead, but no useful output.

So the bug is memory related by the look of it.

Tim.

Robert Wall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

That's useful to know, thank you. I was fairly certain that was indeed what was happening, But I haven't had time to even check what's happened between the emonTx V2 with the old libraries, which worked fine, and the emonTx V3 with the new libraries, which appears to fall over for some people and not for others. I have only the emonTx here, I can't comment about the Arduino platform. What I'm looking to do is rework the sketch so as to reduce the memory demand, if that's possible.

TimSmall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

I've done a bit of that, and shaved about 1k off the one I've got here.  I managed to restore the uno one to operation (whilst still having the big useless string in), but haven't got the Leonardo working yet (resolutely gives rubbish Vrms output).

FWIW, just turning off the LED blink stuff saved a chunk, once the number of digitalWrite() calls fell to zero...

Also worth making all the pin declarations, and calibration values etc. at the top of the sketch consts I think.

TimSmall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

Doh, just realised I've been trying to minimise code size, instead of SRAM size (which is what's going to be in short supply).

Oh well, back to the drawing board.  Still the const thing is probably still a good bet I suppose.

dBC's picture

Re: 3 phase serial-only incorrect voltage reading etc.

Still the const thing is probably still a good bet I suppose.

That should help quite a bit, although obviously not as much as it does on a machine with an MMU.  The compiler treats pre-initialised constant scalar variables much like a #define.  Each time you reference it, the generated code loads up the original literal again, so regardless of what's happened to the RAM location, the original value will be used. 

You can see in the example below, I did manage to corrupt an element in a const array, although I had to work pretty hard to do it.  It was only when I finally randomised the index, that compiler stopped loading up literals, and was forced to use the corrupt RAM location.

const uint32_t test_array[] = {
  0x1000,
  0x1001,
  0x1002,
  0x1003,
  0x1004,
  0x1005,
  0x1006,
  0x1007,
  0x1008,
  0x1009,
  0x100a,
  0x100b,
  0x100c,
  0x100d
};
const uint32_t *cp;
uint32_t *p;
int index;

void setup()
{
  Serial.begin(115200);
  Serial.println("Hello world");
  index = random(0,13);
  Serial.print("index: ");
  Serial.println(index);
  Serial.print("test_array[index]: ");
  Serial.println(test_array[index], HEX);
}

void loop()
{
  cp = &test_array[index];
  p = (uint32_t*)cp;
  *p = 0xcafebabe;
  Serial.print("test_array[index]: ");
  Serial.println(test_array[index], HEX);
  delay(1000);
}

produces:

Hello world
index: 11
test_array[index]: 100B
test_array[index]: CAFEBABE

 

 

By contrast, on a unix machine with an MMU, the constant variables in the .rodata section are mapped to read only pages of memory, then you get instant notification of who's doing the corruption:

#include <stdio.h>
#include <stdint.h>

const uint32_t test_var = 0xdeadbeef;
const uint32_t *cp;
uint32_t *p;

main () {
  printf("Hello world\n");
  cp = &test_var;
  p = (uint32_t*)cp;
  *p = 0xcafebabe;
  printf("test_var: %x\n", test_var);
}

produces:

(gdb) r
Starting program: test 
Hello world

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400572 in main () at test.c:12
12      *p = 0xcafebabe;
(gdb) 
 
TimSmall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

Looks like the cause of the bug is the readVcc() code, which doesn't work on the ATmega32u4 (and returns incorrect and fluctuating values).

In looking for the bug I made out a few other minor changes to the code to fix some compile warnings and reduce the SRAM footprint too.  I'll publish updated code when I get a chance - probably next week some point...

Robert Wall's picture

Re: 3 phase serial-only incorrect voltage reading etc.

I'm not surprised, that (readVcc( ) ) has had many tweaks as new variants of the Arduino range have appeared.

The easy work-around, if you're using a mains supply, is to forget readVcc( ) and put the correct constant in its place for your dc supply voltage - given that the 5 V (?) regulator is stable. If it isn't, you'll need Plan A and add a patch to readVcc( ), because while the initial value of the internal reference is unknown to better than 10% (so a lot worse than most regulators), its stability, both long-term and under load and temperature changes, should be very much better than most regulators.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.