Recent

Author Topic: debugging code for te ACS712, with ATMEGA328P  (Read 1304 times)

pascalbythree

  • Sr. Member
  • ****
  • Posts: 270
debugging code for te ACS712, with ATMEGA328P
« on: January 22, 2025, 12:43:15 pm »
Can somebody help me out debugging this piece of source code? To read the mA from the ACS712.

PS: A underhand unit for this is maybe a better help.

Greets, Wouter van Wegen, PascalByThree


Code: Pascal  [Select][+][-]
  1. program WVW_ACS712;
  2.  
  3. uses
  4.   consoleio, uart, delay;
  5.  
  6. const
  7.    mVperAmp = 100; // 100; // use 100 for 20A Module and 66 for 30A Module
  8.    ACSoffset = 2500;
  9.  
  10.  
  11. var RawValue : DWord;
  12.     voltage : DWord;
  13.     Amps: Dword;
  14.     counter : integer;
  15.  
  16.  
  17. //****************************************************************************************************************
  18. procedure ModePortB(Pin: byte; Value: Boolean); begin if Value then begin DDRB := DDRB or (1 shl pin);  end else begin DDRB := DDRB and not (1 shl pin);  end; end;
  19. procedure WritePortB(Pin: byte; Value: Boolean); begin if Value then begin PORTB := PORTB or (1 shl pin); end else begin PORTB := PORTB and not (1 shl pin); end; end;
  20. procedure ModePortD(Pin: byte; Value: Boolean); begin if Value then begin DDRD := DDRD or (1 shl pin);  end else begin DDRD := DDRD and not (1 shl pin);  end; end;
  21. procedure WritePortD(Pin: byte; Value: Boolean); begin if Value then begin PORTD := PORTD or (1 shl pin); end else begin PORTD := PORTD and not (1 shl pin); end; end;
  22. function ReadPortD(bit: byte): Boolean;         begin Result := PIND and (1 shl bit) <> 0; end;
  23. function ReadPortB(bit: byte): Boolean;         begin Result := PINB and (1 shl bit) <> 0; end;
  24. function IntToStr(const i: Integer): string; begin Str(i, Result); end;
  25. function StrToInt(const s: string): Integer; var code: Integer; begin Val(s, Result, code); end;
  26. //****************************************************************************************************************
  27.  
  28. procedure ADC_Init;
  29. const
  30.    Port = 0;
  31. begin
  32.   ADMUX := (1 shl REFS) or (Port and $0F);
  33.   ADCSRA := %111 or (1 shl ADEN);
  34. end;
  35.  
  36. function ADC_Read(Port : byte) : integer;
  37. begin
  38.    ADMUX := (1 shl REFS) or (Port and $0F); // Specify port
  39.    ADCSRA := ADCSRA or ( 1 shl ADSC );       // Start measuring
  40.  
  41.    while (ADCSRA and (1 shl ADSC)) <> 0 do   // Wait until measured
  42.      begin
  43.      end;
  44.  
  45.    Result := ADC; // Read out the measured value
  46. end;
  47.  
  48.  
  49. function WriteChar(ACh: char; AUserData: pointer): boolean;
  50. begin
  51.   WriteChar := true;
  52.   uart.uart_transmit(ord(Ach));
  53. end;
  54.  
  55. function ReadChar(var ACh: char; AUserData: pointer): boolean;
  56. begin
  57.   ReadChar:=true;
  58.   ACh := char(uart.uart_receive);
  59. end;
  60.  
  61. procedure initIO;
  62. begin
  63.   uart_init1(115200, true);
  64.   OpenIO(Input, @WriteChar, @ReadChar, fmInput, nil);
  65.   OpenIO(Output, @WriteChar, @ReadChar, fmOutput, nil);
  66.   OpenIO(ErrOutput, @WriteChar, @ReadChar, fmOutput, nil);
  67.   OpenIO(StdOut, @WriteChar, @ReadChar, fmOutput, nil);
  68.   OpenIO(StdErr, @WriteChar, @ReadChar, fmOutput, nil);
  69. end;
  70.  
  71. begin
  72.   initIO;
  73.   ModePortB(0,True);
  74.  
  75.  
  76.    // Initialize ADC
  77.    ADC_Init;
  78.  
  79.    counter := 0;
  80.    repeat
  81.       counter := counter + 1;
  82.       if counter = 100 then counter := 1;
  83.  
  84. //***************** PART TO DEBUG FORUM ************************
  85.      RawValue := ADC_Read(0);
  86.      voltage := (RawValue * 5000) div 1024;
  87.      Amps := Voltage - ACSoffset;
  88.      Amps := Amps div mVperAmp;
  89. //*****************************************************************************    
  90.  
  91.  
  92.      WriteLn('***************************');      
  93.      WriteLn('counter: '+IntToStr(counter));
  94.      WriteLn('RawValue: '+IntToStr(RawValue));    
  95.      WriteLn('Amps: '+IntToStr(Amps));    
  96.      WriteLn('***************************');      
  97.  
  98.      WritePortB(0,True); // Status LED ON
  99.      delay_ms(25);
  100.      WritePortB(0,False);
  101.      delay_ms(25); // Status LED OFF
  102.    until 1=2;
  103.  
  104. end.
« Last Edit: January 22, 2025, 12:44:51 pm by pascalbythree »

Laksen

  • Hero Member
  • *****
  • Posts: 794
    • J-Software
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #1 on: January 22, 2025, 01:15:12 pm »
What's the problem?

Khrys

  • Full Member
  • ***
  • Posts: 155
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #2 on: January 22, 2025, 01:19:14 pm »
The only thing that caught my eye at first glance is that  ADC_Read  returns a signed integer even though  ADC  is unsigned, but that shouldn't matter since it's never greater than 1023 anyway... what exactly is the problem you're having?

ccrause

  • Hero Member
  • *****
  • Posts: 998
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #3 on: January 22, 2025, 01:25:54 pm »
Can somebody help me out debugging this piece of source code? To read the mA from the ACS712.
What problem do you observe?  What tests have you done, and what measurements were obtained?

MarkMLl

  • Hero Member
  • *****
  • Posts: 8231
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #4 on: January 22, 2025, 01:42:17 pm »
Can somebody help me out debugging this piece of source code? To read the mA from the ACS712.
What problem do you observe?  What tests have you done, and what measurements were obtained?

Have you successfully loaded the code onto the target?

Have you verified- e.g. by a startup message- that the expected code is running?

How does the structure of your code compare to examples written in e.g. C?

Have you read and complied with the device datasheet?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

ackarwow

  • Full Member
  • ***
  • Posts: 131
    • Andrzej Karwowski's Homepage
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #5 on: January 22, 2025, 06:05:31 pm »
Hi @pascalbythree

If your code compiles without problems but does not work as you expect, you can try to "debug" it "manually" by connecting an LED and flashing it at the right moment. With a bit of luck, you can find the code that does not work as you expect. For example, a procedure that should not be executed but is executed, or does not executed while it should...

dseligo

  • Hero Member
  • *****
  • Posts: 1462
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #6 on: January 22, 2025, 10:52:23 pm »
Can somebody help me out debugging this piece of source code? To read the mA from the ACS712.

I tried your code (I used potentiometer instead of ACS712) and it seems to work fine.

Pot little above half:
Code: Text  [Select][+][-]
  1. ***************************
  2. counter: 23
  3. RawValue: 619
  4. Amps: 5
  5. ***************************
  6. ***************************
  7. counter: 24
  8. RawValue: 617
  9. Amps: 5
  10. ***************************

Pot full:
Code: Text  [Select][+][-]
  1. ***************************
  2. counter: 90
  3. RawValue: 1023
  4. Amps: 24
  5. ***************************
  6. ***************************
  7. counter: 91
  8. RawValue: 1023
  9. Amps: 24
  10. ***************************

Pot minimum:
Code: Text  [Select][+][-]
  1. ***************************
  2. counter: 12
  3. RawValue: 0
  4. Amps: 23567
  5. ***************************
  6. ***************************
  7. counter: 13
  8. RawValue: 0
  9. Amps: 23567
  10. ***************************

From 0 to 2500mV you have incorrect Amps values because you subtract 2500 (offset) and you get negative number which doesn't divide properly. Maybe that is your problem?

dseligo

  • Hero Member
  • *****
  • Posts: 1462
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #7 on: January 22, 2025, 11:03:34 pm »
If negative amps are problem, then solution is simple: you just change Amps type to Longint instead of DWord:
Code: Pascal  [Select][+][-]
  1. Amps: Longint;

And then when pot is at 0 I have:
Code: Text  [Select][+][-]
  1. **************************
  2. counter: 72
  3. RawValue: 0
  4. Amps: -25
  5. ***************************

And at quarter of turn:
Code: Text  [Select][+][-]
  1. ***************************
  2. counter: 98
  3. RawValue: 252
  4. Amps: -12
  5. ***************************

pascalbythree

  • Sr. Member
  • ****
  • Posts: 270
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #8 on: January 23, 2025, 11:28:14 am »
Or is this already working ? And only need to convert AMPS variable to mA ?

I just need to read out from 10mA to lets say 500mA

PS: the test with a 10K potmeter is going from RawValue = 0 to  RawValue = 1023
« Last Edit: January 23, 2025, 11:46:54 am by pascalbythree »

dseligo

  • Hero Member
  • *****
  • Posts: 1462
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #9 on: January 23, 2025, 11:43:55 am »
Or is this already working ? And only need to convert AMPS variable to mA ?

Did you change from Amps: Dword; to Amps: Longint;?

Quote
I just need to read out from 10mA to lets say 500mA

I also think that it would be better to use mA instead of A.
In line where you convert mV to A (Amps := Amps div mVperAmp;), you could just multiply it by 10 to get mA: Amps := Amps * 10;.

Khrys

  • Full Member
  • ***
  • Posts: 155
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #10 on: January 23, 2025, 11:54:22 am »
If negative amps are problem, then solution is simple: you just change Amps type to Longint instead of DWord:
Code: Pascal  [Select][+][-]
  1. Amps: Longint;

And then when pot is at 0 I have:
Code: Text  [Select][+][-]
  1. **************************
  2. counter: 72
  3. RawValue: 0
  4. Amps: -25
  5. ***************************

This is the correct solution. 4294967271  is  0xFFFFFFE7  in hexadecimal and equal to  -25  if interpreted as a signed 32-bit integer. When  RawValue = 0, your output and that of @dseligo match - it's just wrongly formatted.

pascalbythree

  • Sr. Member
  • ****
  • Posts: 270
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #11 on: January 23, 2025, 11:57:39 am »
Code: Pascal  [Select][+][-]
  1.      RawValue := ADC_Read(3);
  2.      voltage := (RawValue * 5000) div 1024;
  3.      Amps := Voltage - ACSoffset;
  4.      Amps := Amps div mVperAmp;
  5.      Amps := Amps * 10;

like this ? Just to read out mA in a integer ?
« Last Edit: January 23, 2025, 12:00:32 pm by pascalbythree »

dseligo

  • Hero Member
  • *****
  • Posts: 1462
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #12 on: January 23, 2025, 12:08:18 pm »
Code: Pascal  [Select][+][-]
  1.      RawValue := ADC_Read(3);
  2.      voltage := (RawValue * 5000) div 1024;
  3.      Amps := Voltage - ACSoffset;
  4.      // Amps := Amps div mVperAmp; // this is commented
  5.      Amps := Amps * 10;

like this ? Just to read out mA in a integer ?

Just multiply with 10, don't divide with mVperAmp.

And change declaration of Amps so it will calculate negative values correctly:
Code: Pascal  [Select][+][-]
  1. var RawValue : DWord;
  2.     voltage : DWord;
  3.     Amps: Longint; // <-------------------- change it like this
  4.     counter : integer;

pascalbythree

  • Sr. Member
  • ****
  • Posts: 270
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #13 on: January 23, 2025, 12:42:32 pm »
Thank you bothers! it got to work. Even though the incoming values are quite unstable.

Will be Back!

someday in another topic.  :-X

dseligo

  • Hero Member
  • *****
  • Posts: 1462
Re: debugging code for te ACS712, with ATMEGA328P
« Reply #14 on: January 23, 2025, 12:57:05 pm »
Thank you bothers! it got to work. Even though the incoming values are quite unstable.

What are you measuring?
Maybe current really varies with time. If there are small differences then you could average it in software. Or you could filter input signal by putting correct capacitor to the FILTER pin of the ACS712.
If you are measuring AC currents, maybe you want to rectify output. Look at the Allegro's datasheet, Application 4 example.

 

TinyPortal © 2005-2018