Flaw in code and I can't find it?

Hello.
I am collecting samples from four sensors, placing them in a 2 dimensional array ReadingArray. The for loop sets the current to the PCB and then the inner loop collects samples for each. Each time the arrays are built I then call the average() function. I would expect the printlnf in average to print four values per call of average(). Instead I see what you see below…

Some definitions:
global

#define NUMBER_SAMPLES 10//80
#define NUMBER_SENSORS 4

uint16_t ReadingArray[4][80];
uint8_t readCycle = 0;
uint8_t current = 0;

I have the following code block in a state machine that lives in the loop:

          case READING:
            for (current = 0; current < 4; current++){
              DAC_Load_Value(dacValues[current]);
              for (uint8_t i = 0; i < NUMBER_SAMPLES; i++){
                  ReadingArray[0][i] = analogRead(Vbias);
                  ReadingArray[1][i] = analogRead(SiPM_current);
                  ReadingArray[2][i] = analogRead(LED1_current);
                  ReadingArray[3][i] = analogRead(LED2_current);
              }
              SensorData.w_temp[readCycle][current] = ReadWaterTemp();
              SensorData.bd_temp[readCycle][current] = ReadIntTemp();
              average();
            }
            readCycle++;
            sm = SOLENOID_POWER;
            break;

The function average() …see below:

void average(){
  unsigned long sum = 0;
  float avg = 0;
  Serial.printlnf("%d --- Cycle, %d ---- Current", readCycle, current);
  for (uint8_t sensor = 0; sensor < NUMBER_SENSORS; sensor++){
    for(uint8_t sample = 0; sample < NUMBER_SAMPLES; sample++){
      sum += ReadingArray[sensor][sample];
    }
    avg = ((float)(sum))/NUMBER_SAMPLES * 3.3/4096;  
    sum = 0;
  
    switch (sensor){
      case 0:
        SensorData.Vbias[readCycle][sensor] = avg;  
        break;
      case 1:
        SensorData.SiPMCurrent[readCycle][sensor] = avg; 
        break;
      case 2:
        SensorData.LEDCurrent[readCycle][0][sensor] = avg; 
        break;
      case 3:
        SensorData.LEDCurrent[readCycle][1][sensor] = avg; 
        break;
      default:
        break;
    }
  }
  for (uint8_t sensor = 0; sensor < NUMBER_SENSORS; sensor++){
    Serial.printlnf("%.2f", SensorData.Vbias[readCycle][sensor]);      
    Serial.printlnf("%.2f", SensorData.SiPMCurrent[readCycle][sensor]);
    Serial.printlnf("%.2f", SensorData.LEDCurrent[readCycle][0][sensor]);
    Serial.printlnf("%.2f", SensorData.LEDCurrent[readCycle][1][sensor]);
  }

}

The printout I receive looks like the following:
0 — Cycle, 0 ---- Current
2.36
0.00
0.00
0.00
0.00
3.19
0.00
0.00
0.00
0.00
0.10
0.00
0 — Cycle, 1 ---- Current
2.36
0.00
0.00
0.00
0.00
3.18
0.00
0.00
0.00
0.00
0.00
0.00
0 — Cycle, 2 ---- Current
2.36
0.00
0.00
0.00
0.00
3.18
0.00
0.00
0.00
0.00
1.21
0.00
0 — Cycle, 3 ---- Current
2.36
0.00
0.00
0.00
0.00
3.18
0.00
0.00
0.00
0.00
0.76
0.00

I’m surprised that you don’t see 16 (+1 heading) lines per call.
You are printing four lines (individual statements) four times (for() loop) and that four times (individual calls of average() within outer for() loop).

1 Like

I know right??? So I’ve moved the printlnf out of the case statement (see below) and now it is printing the 16 you thought it should…I still have code issues bcz if I use avg in the print statements I get numbers that look good (all 16 per shot)…But if I use the structure elements as you see I get a ton of 0’s…I now see why I get these 0’s but I am having a terrible time setting a pointer up to the structure:

void average(){
  unsigned long sum = 0;
  float avg[NUMBER_SENSORS] = {0};
  Serial.printlnf("%d --- Cycle, %d ---- Current", readCycle, current);
  for (uint8_t sensor = 0; sensor < NUMBER_SENSORS; sensor++){
    for(uint8_t sample = 0; sample < NUMBER_SAMPLES; sample++){
      sum += ReadingArray[sensor][sample];
    }
    avg[sensor] = ((float)(sum))/NUMBER_SAMPLES * 3.3/4096;  
    sum = 0;
  
    switch (sensor){
      case 0:
        SensorData.Vbias[readCycle][sensor] = avg[0];  
        break;
      case 1:
        SensorData.SiPMCurrent[readCycle][sensor] = avg[1]; 
        break;
      case 2:
        SensorData.LEDCurrent[readCycle][0][sensor] = avg[2]; 
        break;
      case 3:
        SensorData.LEDCurrent[readCycle][1][sensor] = avg[3]; 
        break;
      default:
        break;
    }
  }
  for (uint8_t sensor = 0; sensor < NUMBER_SENSORS; sensor++){
    Serial.printlnf("%.2f", SensorData.Vbias[readCycle][sensor]);      
    Serial.printlnf("%.2f", SensorData.SiPMCurrent[readCycle][sensor]);
    Serial.printlnf("%.2f", SensorData.LEDCurrent[readCycle][0][sensor]);
    Serial.printlnf("%.2f", SensorData.LEDCurrent[readCycle][1][sensor]);
  }

if you use average above it works fine…

I am having a fundamental issue (which I posted in another post) with respect to pointers…The follwoing simple thing willl NOT compile in VS

int *p_a;
int a[4];

p_a = &a[0];

WorkBench gives me the following error:
‘p_a’ does not name a type

any ideas ??? This compiles all day in CCS

Are you absolutely sure this is where the error is flagged?
Since this code builds absolutely fine for me I'm pretty sure you have some other code that fails instead.

BTW, in your calculation

You have an off-by-one error.
You'd need to divide by 4095 since the maximum reading of the ADC would be 4095.
For a full amplitude signal the division should result in a factor of 1 but 4095 / 4096 will not give you that.

Also a slight reorder of that calculation will make it slightly shorter and also more "precise"

avg[sensor] = (3.3 * sum) / (NUMBER_SAMPLES * 4095);
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.