CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Logger mystery!!!

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
guy



Joined: 21 Oct 2005
Posts: 296

View user's profile Send private message Visit poster's website

Logger mystery!!!
PostPosted: Sun Sep 10, 2017 12:34 am     Reply with quote

I have a data logger (2 channels) that takes several 10-bit samples from the built-in ADC, accumulates them in a 32-bit array (array to support both channels), calculates an average by dividing the result by the number of samples, then transmits the result.
I connected it to 2 different pressure sensors connected to the same pressurized system and measured the pressure which gradually falls over the weekend.
https://www.flickr.com/photos/14648393@N05/shares/0i1j7t
As you can see from the graph there are 3 glitches where the pressure on both channels seems to rise slightly. I am assuming that this is some kind of SW/HW bug since the pressure is not likely to behave like this.
There could be several reasons in HW and SW for this to happen (reference voltage, ADC non-linearity...) but here comes my question:
Could it be that the division of the 32-bit number by an 8/16 bit number will cause this effect???
The scale on the graph is floating point but this is created later in the process. I checked the integer result of the division and the glitches exist there already.
Another interesting clue is that the rise (glitch) appears in 2 consecutive rising values, not just one, for example
2.517
2.512
2.503
2.498
2.508
2.537

2.527
2.522
2.512

any other ideas welcome.
PIC16LF18855, CCS 5.074
Ttelmah



Joined: 11 Mar 2010
Posts: 19435

View user's profile Send private message

PostPosted: Sun Sep 10, 2017 12:53 am     Reply with quote

No. Division of a 32bit number by a 8/16 bit number is done using a 32bit divide. This is standard C.

Several possibilities:

1) You don't say how the output is synchronised to the sampling?. Is it possible that a value is being output before the sum is complete?.
2) You don't describe your arithmetic to convert the 32bit sum to the final result. Could this be having a step change at particular levels?.
3) Are you sure the sum and division are being being performed with the types as you describe?. You need to look carefully at internal parts of the maths. Any use of intermediate temporary variables?.
4) You talk about multiple channels. Are you sure the arithmetic at all points is talking to the right subscript?.
5) Also, how is the sensor read?. It could have the look of a synchronisation problem between the read and the averaging.

It has the look of something like perhaps every X samples something is out of sync, so a sample is read twice, the array is not cleared, the addition is done an extra time etc..
guy



Joined: 21 Oct 2005
Posts: 296

View user's profile Send private message Visit poster's website

PostPosted: Sun Sep 10, 2017 2:43 am     Reply with quote

Good points Ttelmah:
Ttelmah wrote:
1) You don't say how the output is synchronised to the sampling?. Is it possible that a value is being output before the sum is complete?

The output does not have to be synchronized with the sampling since it divides the accumulated value by the number of samples taken. Both are done in the Main (not in an interrupt / race conditions) so I don't think this is the problem.

Ttelmah wrote:
2) You don't describe your arithmetic to convert the 32bit sum to the final result. Could this be having a step change at particular levels?
if you are willing to go over the code I would appreciate it.
Code:

int16 sampleCh(byte ch) {
   // don't forget to turn off ADC !
   unsigned int16 l;
   byte q;
      
   l=0;
      
   setup_adc(ADC_CLOCK_DIV_16);   // 8MHz TAD=2uS
      
   if(ch==2) {         // test battery
      SETUP_ADC_PORTS(sAN0|sAN1|sAN3|sAN15,VSS_VDD);   // sample 2v with VDD ref
      SET_ADC_CHANNEL(3);   // AN3
   }
   else {            // normal analog channels
      SETUP_ADC_PORTS(sAN0|sAN1|sAN3|sAN15,VSS_VREF);
      SET_ADC_CHANNEL(ch);
   }
   READ_ADC();   // DUMP
      
   for(q=0;q<16;q++) {
      delay_us(100);
      l=(long)(l+READ_ADC());
   }
      #IFDEF TXADC
   printf("sampleCh ch.%u %Lu\r\n",ch,l);
   #ENDIF

   return(l);
}

///////////////////////////

void storeSamples() {
   byte i;
   int32 laulau;
    int16 tmp;
      
   if(newPacketFlag) {
      if(txRstFlag) startNewPacket(PKT_TRX1_RST);
      else startNewPacket(PKT_TRX1_LOG);   // incl. timestamp of NOW
      txRstFlag=0;   // only 1 after reset
      newPacketFlag=0;
   }
      
   for(i=0;i<NUM_AN_CH;i++) {
      if(subSampleCntr>0) {
         laulau=subSampleAcc[i];   // accumulated 10-bit samples
         // accumulated 10 bit*16 samples*subSampleCntr
            tmp=subSampleCntr;
            tmp<<=4;                // *16
      #IFDEF TXADC
   printf("storeSamples ch.%u %ld / %Lu\r\n",i,laulau,tmp);
   #ENDIF
         laulau=laulau/tmp; // divide by 16, divide by subSampleCntr
      }
      else laulau=0;   // ERROR!
      write_mem_word(laulau);
         #IFDEF TXADC
       printf(" = %u %u\r\n",memo[memoPtr-2],memo[memoPtr-1]);
       #ENDIF
   }
}

////////////////////////

void handleSampling() {      // general sampling handler
   byte i;
      
   if(subSampleFlag) {
      restart_wdt();
      subSampleFlag=0;
      output_high(DC5V_EN);   // turn on 5V
      delay_ms(SAMPLE_DELAY);         //!!!
      
      for(i=0;i<NUM_AN_CH;i++) {
         subSampleAcc[i]+=(int32)sampleCh(i);// 32-bit accumulator, accumulate 10 bit*16 samples*subSampleCntr
      }
      setup_adc(ADC_OFF);
      output_low(DC5V_EN);   // turn off 5V
      subSampleCntr++;
   }

   if(storeSampleFlag) {
      storeSampleFlag=0;
      storeSamples();
       newSample();    //!!!
      subSampleTmr=2;   // sync subsampling with storage - 2sec after store
   }
}


Ttelmah wrote:
3) Are you sure the sum and division are being being performed with the types as you describe?. You need to look carefully at internal parts of the maths. Any use of intermediate temporary variables?
I already had issues with types & type casting. I *think* it was solved already. See the code above.
Ttelmah wrote:
4) You talk about multiple channels. Are you sure the arithmetic at all points is talking to the right subscript?
I believe so.
Ttelmah wrote:
5) Also, how is the sensor read?. It could have the look of a synchronisation problem between the read and the averaging.

The sensor is powered every 30 sec to take a sample. I expect a slow decay in pressure with no surprises. Also the noise is low and the final averaging is (16 consecutive burst samples) * (12 sampling bursts) = 192 samples averaged.

I put an oscilloscope + serial monitor to follow the readings and calculations, hoping to find the bug somewhere, but recreating it is difficult and time consuming.
guy



Joined: 21 Oct 2005
Posts: 296

View user's profile Send private message Visit poster's website

PostPosted: Sun Sep 10, 2017 5:15 am     Reply with quote

ok, this is going into the HW area but any help would still be appreciated.
My circuit works on 3V and an MCP16251 boost regulator supplies 5V to the sensor. Both the 5V and the sensor signal are scaled down using resistors to 0-2V scale so that the 5V creates a 2V reference value (connected to Vref+) and the sensor signal is sampled using that ref. The sensor itself reacts to changes in the 5V supply although not linearly i.e. it does not have a built-in reference.
I've been sampling the lines for several hours and at some point I see the 5V supply going slightly down from 5.00V to 4.90V.
The slight drop in the supply didn't happen for hours, then appeared for just a few samples (a couple of minutes) and recovered.
At the moment I am working with 2x AA batteries as power source but the graph I sent was made using a lab power supply.
Any ideas what would affect the output of the regulator in such a way, assuming there is no significant change in environment, load, supply? Also theoretically the supply voltage should be cancelled out if the signal is ratiometric to the supply and the supply is used as reference, but the linearity of the sensor is not really guaranteed.
(edit)
Even a temporary change in supply doesn't explain the glitch+shift up of the graphs... I am lost...


Last edited by guy on Sun Sep 10, 2017 5:30 am; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9198
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Sep 10, 2017 5:17 am     Reply with quote

Can't speak about the math but...

I notice that 'restart_wdt' is in your code. Have you tried without using the WDT ? At least try without, if it still 'glitches' then you KNOW it's not a WDT caused problem (well, hopefully..).

I'd dump out the raw data at every step....follow the bits, so to speak. Send all data to a PC, save to a CSV formatted file, then run Excel and see if there IS a pattern. Let it run for few hours, say overnight. It has to collect enough data to see the 'pattern', if there is one.

You control power to the sensors. By dumping the raw data, you can see if the powering up is the cause. Perhaps one sensor is faulty? Can you swap sensors, though the math you do might not show up which is bad...
again, a log of raw sensor data (ADC results) and EVERY interim calculation should show WHERE the bad number is coming from.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19435

View user's profile Send private message

PostPosted: Tue Sep 12, 2017 1:04 am     Reply with quote

Some comments:

Are you sure your ADC supports operation off a 2v reference?.
Most PIC's don't. The minimum ADC span for full accuracy is typically perhaps 2.5v. Won't give the spikes, but will degrade accuracy.
Check the PIC data sheet.

Now you switch ADC modes. If you are sampling AN3, then you are using the supply as the Vref. If you are changing channels like this, don't enable the other multiplexer inputs. So:
Code:

   if(ch==2) {         // test battery
      SETUP_ADC_PORTS(sAN3,VSS_VDD);   // sample 2v with VDD ref
      SET_ADC_CHANNEL(3);   // AN3
   }

and the other way for the other channels.

How often does CH==2?. Could this be when the glitch happens?. What is the output impedance of the voltage sources?. One thought is that the impedance is high, and when you switch to measuring the supply, it then takes time for the ADC Vref to stabilise. I'd honestly suggest using an external Vref, at perhaps 2.5v, and measuring everything relative to one reference.
When you change Vref, all the internal circuitry of the ADC has to charge to the new voltage. Can both your sources supply the current the Vref requires?. Has significant spikes during sampling (depends on the PIC, which you haven't told us). How is the Vref pin smoothed?.

What processor are you on?. PIC16, 18, 24, 3/ etc.?
I notice you have a variable declared as int16, and use:
tmp<<=4; // *16

This will not work correctly if int16 is signed. It is by default on a PIC24 etc..
It is honestly better to actually use the arithmetic you want. So *16. This way faults like this won't appear.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group