How to read weight data from Avia HX711. I am using NRF52840DK board with NRF Connect SDK (2.6.1)

I am developing a project in which a weight analog data is converted as digital by Aviva HX711.

In the host board NRF52840DK, I want to read the wight value.

I have attached the datasheet of the HX711 we are using.

2046.HX711.pdf

Parents
  • I have thought some more about this. Initially I was thinking you could use SPI or UART to simulate the proprietary serial protocol, but I think that would be difficult, because you need either 25, 26 and 27 pulses. SPI will give n*8 pulses, so that won't work. UART on the other hand will not work, because it expects a stop bit to always be high, so it will report communication errors. It may be that you need to set up something using PPI

    What this does is that it couples together some peripherals. The challenge is that while you could do this just by setting up a regular function and toggling the clock pulse up and down manually 25 times, this may not work because you may be interrupted by something else e.g. while the clock pin is high, which will cause it to power down the sensor. You could then just try again, if you are fine with it failing from time to time (how often depends on the rest of your application, and what it is doing). By using PPI you can couple together events and tasks in the peripherals, so that they will trigger automatically, without the need of the CPU.

    So I think the best way to do this is to "automate" the reading of 1 bit. You can set up a timer to start, then at a given time, you can toggle the clock pin high, and at another time set it back low. All this can be done in a sequence without involving the CPU (other than to start the sequence). Then you can chose whether you hook onto the event that sets the clock pin back to low to generate another interrupt for your CPU (using the EGU, Event Generator Unit), but the easier way is perhaps just to add a short sleep from where you start the timer, so that you know it is done before sampling the pin, and repeat the process another 24 times. This way, you don't get interrupted while the clock pin is high, causing the sensor to enter power off mode. 

    There are libraries with APIs to use for the PPI, but for simple tasks like this, I usually prefer just interfacing the PPI registers directly. 

    Pseudo code:

    volatile uint32 sample_value = 0;
    void init_ppi_function(void)
    {
        set up TIMER3 in timer mode with correct frequency. 
        set up so that clock pin goes high when TIMER3 reaches value A
        set up so that clock pin goes low when TIMER3 reaches value B (1, maybe 2µs after value A).
    }
    
    uint32_t sample_bit(void)
    {
        //read gpio and return 0x00 if low and 0x01 if high.
    }
    
    void read_sensor(void)
    {
        for (int i=0; i<26; i++)
        {
            sample_value |= sample_bit();
            if (i != 25)
            {
                sample_value << 1;
            }
        }
    }
    
    int main(void)
    {
        ... //all the other things you set up.
        init_ppi_function();
        ...
        while (true)
        {
            k_sleep(K_MSEC(1000))
            read_sensor();
        }
    }

    Now, I don't know if you are using NCS or the nRF5 SDK. However, interfacing the PPI registers doesn't really care what SDK version you are using. For a sample, you can check out this PPI sample that shows how to set up a PWM signal using PPI + GPIOTE + TIMER:

    https://github.com/edvinand/ppi_pwm_hands_on

    Best regards,

    Edvin

Reply
  • I have thought some more about this. Initially I was thinking you could use SPI or UART to simulate the proprietary serial protocol, but I think that would be difficult, because you need either 25, 26 and 27 pulses. SPI will give n*8 pulses, so that won't work. UART on the other hand will not work, because it expects a stop bit to always be high, so it will report communication errors. It may be that you need to set up something using PPI

    What this does is that it couples together some peripherals. The challenge is that while you could do this just by setting up a regular function and toggling the clock pulse up and down manually 25 times, this may not work because you may be interrupted by something else e.g. while the clock pin is high, which will cause it to power down the sensor. You could then just try again, if you are fine with it failing from time to time (how often depends on the rest of your application, and what it is doing). By using PPI you can couple together events and tasks in the peripherals, so that they will trigger automatically, without the need of the CPU.

    So I think the best way to do this is to "automate" the reading of 1 bit. You can set up a timer to start, then at a given time, you can toggle the clock pin high, and at another time set it back low. All this can be done in a sequence without involving the CPU (other than to start the sequence). Then you can chose whether you hook onto the event that sets the clock pin back to low to generate another interrupt for your CPU (using the EGU, Event Generator Unit), but the easier way is perhaps just to add a short sleep from where you start the timer, so that you know it is done before sampling the pin, and repeat the process another 24 times. This way, you don't get interrupted while the clock pin is high, causing the sensor to enter power off mode. 

    There are libraries with APIs to use for the PPI, but for simple tasks like this, I usually prefer just interfacing the PPI registers directly. 

    Pseudo code:

    volatile uint32 sample_value = 0;
    void init_ppi_function(void)
    {
        set up TIMER3 in timer mode with correct frequency. 
        set up so that clock pin goes high when TIMER3 reaches value A
        set up so that clock pin goes low when TIMER3 reaches value B (1, maybe 2µs after value A).
    }
    
    uint32_t sample_bit(void)
    {
        //read gpio and return 0x00 if low and 0x01 if high.
    }
    
    void read_sensor(void)
    {
        for (int i=0; i<26; i++)
        {
            sample_value |= sample_bit();
            if (i != 25)
            {
                sample_value << 1;
            }
        }
    }
    
    int main(void)
    {
        ... //all the other things you set up.
        init_ppi_function();
        ...
        while (true)
        {
            k_sleep(K_MSEC(1000))
            read_sensor();
        }
    }

    Now, I don't know if you are using NCS or the nRF5 SDK. However, interfacing the PPI registers doesn't really care what SDK version you are using. For a sample, you can check out this PPI sample that shows how to set up a PWM signal using PPI + GPIOTE + TIMER:

    https://github.com/edvinand/ppi_pwm_hands_on

    Best regards,

    Edvin

Children
No Data
Related