• AVR Freaks

Hot!18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins

Author
Trackhappy
Starting Member
  • Total Posts : 56
  • Reward points : 0
  • Joined: 2016/11/03 16:07:08
  • Location: 0
  • Status: offline
2020/02/18 20:00:46 (permalink)
0

18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins

Hi all,
The background is that I have built a pump controller which currently monitors water flow using 5V pulses from a sensor, and pressure using analog DC from a sensor, and I now want to add pump current draw to the display.
 
I looked at the MCP39F511A, which does all I need and more and presents them out a serial port by request, but I am using the onboard UART for the display and writing a full serial protocol in code is a little too much work for the present. Maybe next design I will use the 40 pin version which has two UART's onboard. I can easily add an ACS770 to the PCB, which gives me an analog output representing the current flow through it.
 
I need to get an idea of how to re-write my code to read two differing ADC inputs. One varies very little over a second (pressure, which I sample and display twice per second), the other will be sampling a 50Hz sine wave to determine RMS current which will obviously need many more samples.
 
Current to voltage and high voltage isolation is taken care of by ACS770 sensor which outputs analog 40mV per amp with zero being at half (5V) rail. At 10 amps for example, sine wave input to ADC pin would be varying between 2.1V and 2.9V.
 
My primary question is what is the best way to re-write to get enough samples to calculate the RMS value  while still sampling my pressure ADC. 
 
The ADC is currently set to FRC, free-running at 600KHz and I just start a conversion each sample time.
 
 
My initialisation routine includes:
 
void ADC_Init(void)
{
    
   //ANSELx registers  
   ANSELA = 0b00000001; //RA0 analog input
// Change to ANSELA = 0b00000011; //RA0 and RA1 analog inputs
   ANSELB = 0x00;
   ANSELC = 0x00;
   //10 bit resolution, result in ADCRESH and ADRESL, Right justified.
    ADON = 0; //Ensure ADC is off
    ADCON0bits.ADFM = 1; //Right justify result into ADRESH and ADRESL
    OSCENbits.ADOEN = 1;
    ADCON0bits.ADCS = 1; //Select FRC Clock 600KHz free-running internal osc
    while (!OSCSTATbits.ADOR); //Wait for AD oscillator to be ready
    ADPCH = 0x00; //RA0 is Analog channel
    ADCON0bits.ADON = 1; //Turn ADC On
}
 
void TIMER_Init(void)
{
//TMR0 8 bit, Prescaler 1:1, Preload TMR0H 20 = 1mS
T0CON0bits.T0EN = 0; //Stop timer0 while we setup parameters
PIE0bits.TMR0IE = 1; //Enable Timer0 Interrupts
T0CON1bits.T0CS = 5; //2 FOSC/4 as source (16Mhz))
T0CON0bits.T016BIT = 0; //Set timer0 as 8 bit
T0CON1bits.T0CKPS = 0; //Prescaler 1:1
T0CON1bits.T0ASYNC = 1; //Async mode - Must be set - bug from errata
TMR0H = 0x20; //Preload 20 into TMR0H counter to make 1mS
TMR0L = 0x00;
PIR0bits.TMR0IF = 0; //Clear Interrupt flag
T0CON0bits.T0EN = 1; //Enable timer 0
}
 

 
Every 500mS I execute this:
 
//Read ADC pressure sensor pin
void Read_Pressure(void)
    {
        ADCON0bits.GO = 1; //Start conversion
        GO_nDONE = 1;
        while (ADCON0bits.GO) continue; //Wait for conversion done
        ADCRead = (ADRESH <<8) + ADRESL; //Concatenate ADC high and ADC low bytes
        SamplePSI = ((ADCRead - 100)/8.1); //Sensor 0 pressure voltage offset
        LastPSI = SamplePSI;
        if (LastPSI > 100) LastPSI = 0; //Sanity check - can't rollover if less than 0.
    }

 
Accuracy is not critical, 5% on the displayed current value (0.1 amps resolution) would be fine and displayed 4 times per second would be ideal. From reading around, I have found varying requirements from 4 samples per cycle being adequate to many more required.
 
Should I, for example, change the ADC to run every millisecond?
Is it still ok to have it running from FRC?
 
My mind tells me that I should sample RA1 every millisecond, take 10 samples and look for the peak, then do the calculation to determine RMS (or just lookup in a table for efficiency). How then, do I sample the pressure in between without dropping too many samples. If I just Read_Pressure at 1mS intervals will there be any issues with the sampling (capacitor charging etc.). 
 
I also see that the processor has a ZCD module. Should I sense the zero cross, then just sample at 5mS from that point (or maybe at 4mS, 5mS, 6mS and average) as it will always be a sine wave at 50Hz.
 
I'd appreciate any insights or thoughts or even better somebody who has actually done it before.
 
Thanks,
Glenn.
 
 
#1

7 Replies Related Threads

    ric
    Super Member
    • Total Posts : 26106
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: 18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins 2020/02/18 20:20:55 (permalink)
    0
    Trackhappy
    ...
    I looked at the MCP39F511A, which does all I need and more and presents them out a serial port by request, but I am using the onboard UART for the display and writing a full serial protocol in code is a little too much work for the present. Maybe next design I will use the 40 pin version which has two UART's onboard. I can easily add an ACS770 to the PCB, which gives me an analog output representing the current flow through it.

    Couldn't you just use PPS to temporarily swap which pins your single USART is connected to?
    (I know it works, I'm doing precisely that on some PIC16F designs)
     
    Edit: Actually, you already have two USARTs. Have you just run out of pins?
     
     
    post edited by ric - 2020/02/18 20:24:05

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    Trackhappy
    Starting Member
    • Total Posts : 56
    • Reward points : 0
    • Joined: 2016/11/03 16:07:08
    • Location: 0
    • Status: offline
    Re: 18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins 2020/02/18 20:44:15 (permalink)
    0
    Hi ric,
    Unfortunately, I am using the 28 pin version, which only has one UART. I'd love to learn how you use PPS like that. 
    Here is my PPS code:

    PPSLOCKbits.PPSLOCKED = 0x00; // unlock PPS
    RX1PPS = 0x17; //RC7->EUSART1:RX1; Pin 18
    RC6PPS = 0x09; //RC6->EUSART1:TX1; Pin 17

    //PPS lock sequence
    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0x01; // lock PPS

    I am constantly reading the UART register for touch screen events, I guess I'd halt that, change pins with PPS, then send the request, wait for the reply, change PPS back and restart the touch read process.
    First, I have to figure out how to solder one of those tiny little babies onto the board... ;)
     
    #3
    ric
    Super Member
    • Total Posts : 26106
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: 18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins 2020/02/18 20:49:11 (permalink)
    0
    Trackhappy
    Hi ric,
    Unfortunately, I am using the 28 pin version, which only has one UART.

    Really?
    My copy of the datasheet says it has two.
    http://ww1.microchip.com/...DS40001816F.pdf#page=4
     
    post edited by ric - 2020/02/18 20:51:30

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #4
    Trackhappy
    Starting Member
    • Total Posts : 56
    • Reward points : 0
    • Joined: 2016/11/03 16:07:08
    • Location: 0
    • Status: offline
    Re: 18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins 2020/02/18 20:57:46 (permalink)
    0
    I'd love that to be true, yes it says two until you go looking for the second pins in the pin table for the 28 pin and RX2 and TX2 aren't there. Very pleased if somebody could find them for me. :)
    post edited by Trackhappy - 2020/02/18 21:01:50
    #5
    ric
    Super Member
    • Total Posts : 26106
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: 18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins 2020/02/18 21:03:23 (permalink)
    +2 (2)
    You have to use PPS for them. They just don't have any default positions.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    Trackhappy
    Starting Member
    • Total Posts : 56
    • Reward points : 0
    • Joined: 2016/11/03 16:07:08
    • Location: 0
    • Status: offline
    Re: 18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins 2020/02/18 21:08:39 (permalink)
    0
    That right there is the value of this forum. I hadn't even thought of that. I actually built the PCB with a daughter board for the 511A so if I can use the pins I laid out... good to go.
     
    Thank you again.
     
    I'd still like to learn how I could have done it though. I am fairly new at this.
    #7
    ric
    Super Member
    • Total Posts : 26106
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: 18F26K40 single ADC to read RMS voltage and slow rate DC voltage on different pins 2020/02/18 21:16:58 (permalink)
    +1 (1)
    Trackhappy
    ...
    I'd still like to learn how I could have done it though. I am fairly new at this.

    Do you mean by using the ADC?
    You would have to set the ADC's "acquisition timer", and select the desired input just before setting the GO/DONE bit.
    Also note, in this code:
            ADCON0bits.GO = 1; //Start conversion
            GO_nDONE = 1;

    You are setting exactly the same bit twice, just using different names for it.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #8
    Jump to:
    © 2020 APG vNext Commercial Version 4.5