InitTimersSafe() messing with analogRead() values

I am working on a project that reads accelerometer data, does some digital signal processing to create a synthesized signal to output to a voice coil motor to relay haptic feedback for teleoperation. I have a program that can run the motor at different frequencies using the PWM lib that allows different frequencies on different pins. I also have a program that can read the accelerometer data and print out its principal component, but when I put them together I just get "ovf" for my accelerometer value. I have been trying to find the problem, and I believe it is the function InitTimersSafe() because when I comment this part out I get readings that I expect. I am not sure why it is affecting my accelerometer readings though, since I don't think analogRead() uses a timer. Is there something in the PWM library that I am missing, or does the library actually affect analogRead()?

Below is my code along with its header file, thanks in advance for any help!

#include "pca.h"
#include <PWM.h>

// Global Variables
int xPin = A2, yPin = A1, zPin = A0;
float xVal, yVal, zVal;
float xOffset, yOffset, zOffset;
int g = 9.81;
float t0 = 0, t, dt;

float input[3] = {0, 0 , 0}, output[3] = {0, 0, 0};

Eloquent::ML::Port::PCA pca;

void setup() 
{
  Serial.begin(9600);
  zeroAvg(); //finding avg to get rid of DC bias
//  Serial.print(xOffset);
//  Serial.print(" ");
//  Serial.print(yOffset);
//  Serial.print(" ");
//  Serial.println(zOffset);
  t0 = millis();

  InitTimersSafe();

//  Serial.println(Timer0_GetFrequency());
//  Serial.println(Timer1_GetFrequency());
}

void loop() 
{
  delay(20);
  xVal = ((analogRead(xPin)/156.0)*g)- xOffset; //reading accelerometer data and getting rid of bias
  yVal = ((analogRead(yPin)/174.0)*g)- yOffset;
  zVal = ((analogRead(zPin)/192.0)*g)- zOffset;

  dt = millis() - t0;
  t = (t0 + dt)/1000;
  t0 = t;
  
//  Serial.print("Acc: "); // printing accel values
//  Serial.print(xVal, 7);
//  Serial.print(",");
//  Serial.print(yVal, 7);
//  Serial.print(",");
//  Serial.print(zVal, 7);
//  Serial.print(",");
//  Serial.println(t);

  input[0] = {xVal};
  input[1] = {yVal};
  input[2] = {zVal};

//  Serial.print("PCA Inputs: "); // printing accel values
//  Serial.print(input[0], 7);
//  Serial.print(",");
//  Serial.print(input[1], 7);
//  Serial.print(",");
//  Serial.print(input[2], 7);
//  Serial.print(",");
//  Serial.println(t);

  pca.transform(input, output);

//  Serial.print("PCA: "); // printing PCA values
  Serial.print(output[0], 7);
//  Serial.print(",");
//  Serial.print(output[1], 7);
//  Serial.print(",");
//  Serial.print(output[5], 7); //idk why but this one seems to give reasonable readings
  Serial.print(",");
  Serial.println(t); 

  delay(200); // so we can actually read the data
}

// function for finding zero mean
void zeroAvg()
{
  int k = 0;
  float xSum = 0, ySum = 0, zSum = 0;
  
  while (k < 1000) //average over 1000 iterations
  {

   xVal = (analogRead(xPin)/156.0)*g;
   yVal = (analogRead(yPin)/174.0)*g;
   zVal = (analogRead(zPin)/192.0)*g;
   
   xSum = xSum + xVal;
   ySum = ySum + yVal;
   zSum = zSum + zVal;
   k++;
  }

  xOffset = xSum/1000; // calculating offset values
  yOffset = ySum/1000;
  zOffset = zSum/1000;
}

This is the pca.h file that is included.

#pragma once
#include <stdarg.h> //<cstdarg>
namespace Eloquent {
    namespace ML {
        namespace Port {
            class PCA {
                public:
                    /**
                    * Apply dimensionality reduction
                    * @warn Will override the source vector if no dest provided!
                    */
                    void transform(float *x, float *dest = NULL) {      
                        static float u[2] = { 0 };
                        u[0] = dot(x,   0.361386591785  , -0.084522514065  , 0.85667060595  , 0.358289197152 );
                        u[1] = dot(x,   0.656588771287  , 0.730161434785  , -0.173372662796  , -0.075481019917 );
                        memcpy(dest != NULL ? dest : x, u, sizeof(float) * 2);
                    }

                protected:
                    /**
                    * Compute dot product with varargs
                    */
                    float dot(float *x, ...) {
                        va_list w;
                        va_start(w, 4);
                        static float mean[] = {  5.843333333333 , 3.057333333333 , 3.758 , 1.199333333333  };
                        float dot = 0.0;

                        for (uint16_t i = 0; i < 4; i++) {
                            dot += (x[i] - mean[i]) * va_arg(w, double);                        }

                        return dot;
                    }
                };
            }
        }
    }

Which Arduino board do you use and which PWM library do you use ?

Do you know the KISS principle ? https://en.wikipedia.org/wiki/KISS_principle.
Why is the code in pca.h so over-complicated ?
Can you turn on all the compiler warnings ? Set the "Compiler warning" to "All" in the preferences.

[ADDED]
For those who want to play with the code: https://wokwi.com/projects/334118194182619732.
The InitTimerSafe() does a lot, and also does something with Timer0. I can not find any connection with analogRead() though. My feeling says it is a memory problem.

I am using a Mega and am using the PWM library that allows you to mess with timers to change the frequency of the pins. Great questions, I have just been prototyping so my code is all over the place, I decided to simplify my Arduino code by running the PCA code in Python instead since I will be needing to do some analysis on Python anyways. This solved my problem, not sure how helpful this will be for people in the future though. Thanks for your help, and thanks for showing me wokwi.com! Looks like a real cool tool.

Good choice.

I think there is a bug in the calculation.
There are three values in "input", which is passed on to "tranform()" which passes it on to "dot()". The "dot()" uses four values of "input".

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