Continued: Using qsort to average readings

@FiDel, Continuing the discussion from Using qsort to average readings:

So I had some time and created an (approx) 4kHz signal on an Arduino and synthesized a pseudo random PWM like this:

void setup()
{
  TCCR1B = TCCR1B & 0b11111000 | 0x02;  //3906Hz
}

void loop()
{
  randomSeed(digitalRead(A0));
  analogWrite(5, 100 + random(5));
  analogWrite(9, 100 + random(5));
  delay(75);
}

and fixed the sketch I offered you to calc the duty cycle (correctly) with floating point numbers and get this output:

tested code (i used only two inputs)

/**************************************************************
 * Duty Cycle analyzer FUNCTION for PWM temperature sensors
 Any pin can be sensor input pin: Specify in function call in the loop()
 For debugging, the serial monitor shows all temperatures on one line
 **************************************************************/


double averageTemperature; 
int pulsePins[] = { D3, D4 };  //, D5, D7, A1, A3, A5, A7, TX };
double Temp[10] = {0}; // All the temperatures into an array!!  // 10 in this example
char resultstr[256] = "";

void setup()
{
  Serial.begin(115200);
  for (int i = 0; i < sizeof(pulsePins) / sizeof(pulsePins[0]); i++)
  {
    pinMode(pulsePins[i], INPUT);
  }
  Particle.variable("result", resultstr, STRING);
  Serial.println("starting");
}

void loop()
{
  strcpy(resultstr, "");  // start with an empty buffer
  averageTemperature = 0;  // get ready to average what we recieve
  for (int i = 0; i < (sizeof(pulsePins) / sizeof(pulsePins[0])); i++) // count our way through all of the pins
  {
    Temp[i] = analyze(pulsePins[i]);
    averageTemperature += Temp[i];  // add all of the readings together
    char myText[15] = "";  // create a little buffer for your reading.
    snprintf(myText, sizeof(myText), "T%d: %5.2fC%s ", i, Temp[i], (i < (sizeof(pulsePins) / sizeof(pulsePins[0]) - 1)) ? "," : " "); // Build your buffer reading by reading
    strcat(resultstr, myText); // bolt on each segment to the buffer
  }
  averageTemperature /= sizeof(pulsePins) / sizeof(pulsePins[0]); // compute the average by dividing by number of readings
  Serial.print("temperatures:");
  Serial.println(resultstr);
  Serial.print("Average = ");
  Serial.println(averageTemperature, 2);
  delay(5000);
}

double analyze(pin_t pulsePin)
{
  double temperature = 0.0;
  const int num_pulses = 100;
  int goodReads = 0;
  double periodDutyCycle[num_pulses] = {0.0};
  RGB.control(true);
  RGB.color(255, 255, 255);  // Making it Red looks lika an error message...
  for (int i = 0; i < num_pulses; i++)  // get num_pulses samples of HIGH and LOW pulses
  {
    unsigned long highPulseTime = 0;
    highPulseTime = pulseIn(pulsePin, HIGH);
    unsigned long lowPulseTime = 0;
    lowPulseTime = pulseIn(pulsePin, LOW);
    periodDutyCycle[i] = double(highPulseTime) / double(highPulseTime + lowPulseTime);  // save individual period duty cycle
  }
  double dutyCycle = 0;
  for (int i = 0; i < num_pulses; i++)
  {
    dutyCycle += periodDutyCycle[i];
  }
  dutyCycle /= num_pulses;
  //Serial.print("DutyCycle = ");
  //Serial.println(dutyCycle);
  temperature = (212.77 * dutyCycle) - 68.085;
  RGB.control(false); // end RGB LED control
  //Serial.println("Returning Temperature: ");
  //Serial.println(temperature);
  return temperature;
}

so, did you want the median value of the accumulated periodDutyCycle[] array or the Temp[] array?

1 Like

Wow, thanks for your efforts @BulldogLowell!
I will try it out when I find a few hours and let you know the results.

Yes, the sorting and selection of the middle values is the key point of this topic…

:older_man: :+1: