1

I am creating a project in nordic Micro that reads a value from an Analog input termninal an output it into UART. I am now trying to compress the data using GE Proficy Historian Compression so that only changed data are outputted in the UART. But my code is not working. Outputted data are sometime still redundant. The idea of the program is to generate an interrupt every certain amout of time, read the adc value and if its different than previous value, output it to the UART port. the algorithm is explained here http://www.evsystems.net/files/GE_Historian_Compression_Overview.ppt The main portion of the code that handles the interrupt is as shown below

void ADC_IRQHandler(void)
{
    /* Clear dataready event */
  NRF_ADC->EVENTS_END = 0;   
    // write ADC value to UART port 

    // Compression Algorithm should occur here
    uint8_t current_Val= NRF_ADC->RESULT;
    //simple_uart_put(current_evaluation);


    // Construct error bands around the held point

    float U_tolerance = current_Val  + error_tolerance;
    float L_tolerance = current_Val - error_tolerance; // integer type is selected since lower tolerance could be negative

    if( first_Run == false)
    {
        float slope = ((current_Val - Archived_Val) / (held_Time - Archived_Time)) ;
        if (slope > U_Slope || slope > L_Slope)
        {
            Archived_Val = current_Val; // update the archived value
            held_Time = 1; // reset held time
            simple_uart_put(current_Val);
            first_Run = true;
            Archived_Val = current_Val;
        }
        else
        {
            float Upper_Slope = (U_tolerance - Archived_Val) /( held_Time - Archived_Time);
            float Lower_Slope  = (L_tolerance - Archived_Val)/(held_Time- Archived_Time);

            if(Upper_Slope < U_Slope) // lowest upper slope is always taken as a blanket boundry
            {
                U_Slope = Upper_Slope;
            }
            if(Lower_Slope < L_Slope)
            {
                L_Slope = Lower_Slope;
            }
            held_Time += time_increment;
        }
    }

    if (first_Run == true) // first held point always outputted
    {
            // calculate the slopes of the two lines 
    float Upper_Slope = (U_tolerance - Start_Up_Val) /( held_Time - Archived_Time);
    float Lower_Slope  = (L_tolerance - Start_Up_Val)/(held_Time- Archived_Time);

        // Update Max and Min slopes

    if(Upper_Slope < U_Slope) // lowest upper slope is always taken as a blanket boundry
    {
            U_Slope = Upper_Slope;
    }
    if(Lower_Slope < L_Slope)
    {
        L_Slope = Lower_Slope;
    }


    held_Time += time_increment;
    first_Run = false;
    Archived_Val = current_Val;
    }

}

The veriables are defined as follow

> uint32_t error_tolerance = 50; // error tolerance value for swining door algorithm
uint8_t Start_Up_Val = 100;
float held_Time = 1;
int Archived_Time = 0;
float U_Slope = 2500;
float L_Slope = 0;
//float slope;
uint8_t Archived_Val;
bool GE_Comp(uint8_t, uint8_t, uint8_t, int);
bool first_Run = true;
float time_increment = 0.1;
Raiyans
  • 11
  • 2
  • 3
    And what problems do you have with the code you show? Doesn't it build? Does it crash? Does it give wrong results? Please elaborate. Also please [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask), and learn how to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – Some programmer dude Aug 15 '15 at 19:50
  • 3
    Your interrupt handler is trying to implement too much functionality. What is its execution time? Implementing `float` calculations within interrupts in an embedded environment is usually a complete no-no. – Weather Vane Aug 15 '15 at 20:09
  • when setting float variables, the setting value should also be float. I.E. each literal float value should contain a decimal point '.' and a trailing 'f' such as: float U_Slope = 2500.f; float L_Slope = 0.f; and float time_increment = 0.1f; – user3629249 Aug 15 '15 at 21:26
  • there seems to be way too much code inside the interrupt handler. Suggest: use a mutex. In the interrupt handler, if time stamp is not clear, flag a data overrun error. otherwise, set the new value in some global variable and set a time stamp. In the main function, watch the time stamp. when the time stamp changes, retrieve the global variable and time stamp. Then clear the time stamp. Then perform the needed processing. – user3629249 Aug 15 '15 at 21:36
  • Ok..thanks you al lfor the responses. @Jochaim. As I said, I still get redundant data out. The output of the device is an uint8_t which means the adc will ouput a value between 0 and 255. So when the output is the same for two consegative runs e.g. 230 and 230, the new value should be discarded. otherwise if there is change, it should be displayed in the UART port. currently, this does not happen. I receive similar value out in the UART Terminal. – Raiyans Aug 17 '15 at 07:37
  • @Weather Vane and user3629249 thanks for the suggestion. I will fix this problem by disabling the interrupt at the beginnning of the algorithm and setting it back again at the end of it. I will let you know about the results. user3629249 this should not be the problem but I will do as you said and give you the feedback. – Raiyans Aug 17 '15 at 07:41
  • 1
    @Raiyans that's ***not*** how you fix the problem. The interrupt will already be disabled at the start of the interrupt. If there are other interrupts of same or lower priority they won't be serviced until yours has finished. As others commented, the way to solve this is to remove most of the weight from the IRQ handler. It will then simply post the raw ADC input value to, let's say `main()` where a loop will detect the change and recalculate what that ADC counter value means for the user. – Weather Vane Aug 17 '15 at 18:55

1 Answers1

0

Thank you all for your contribution and mostly to @Weather Vane . It was exactly as you and others suggested, the interrupt handler was executing too much coding which prohibited it from proper functionality. I now fixed the problem by diverging the parts of the code to the main function as suggested. Regareds

Raiyans
  • 11
  • 2