Working With Sine Waves

Hey guys,

I have a project I am working on, and need some help working with values read from the Arduino.

The project is a Dynamic Wheel Balancer, in order to achieve balance, I run the test and print the values into an excel spreadsheet.
So I read the serial data from the USB port on the computer. I end up with a sine wave that consists of, vibration level and wheel position.
The negative zero(135 in this case) crossing point is the position I will add a compensation weight.

With that said, I wish to hook up an LCD and use it to display the point, instead of using the computer.

I am struggling with picking that negative zero crossing point with the Arduino.

Check out the image attached.

There is a range of position values that cross that 135 point because I measure at a range of RPMs, the plan is to take the position of those points and average them out. But first I need to figure out how to choose those points. Keep in mind that the wave will always change depending on the imbalance characteristics. This means the negative crossing will always change per item tested.

Any ideas?

Screen Shot 2018-03-18 at 3.34.40 PM.png

Yeah, I have an idea. DON'T CROSSPOST.


Seems a bit rude.
You get fired up pretty quick eh, el_supremo?

New to this forum, wasn't having success deleting my other post, got barked at over there too, figured I would switch topics.

Maybe I should try somewhere other then the Arduino forum if my post is too inconvenient.

Seems a bit rude.

Oh dear. I am so ...... nope, I got nothing.

New to this forum

And yet you think those two "sticky" posts at the top of the forum don't apply to you?
You know, the ones that say:
How to use this forum - please read.
Read this before posting a programming question ...
Try reading them.


Okay, el_supremo.

I understand you have spent some time on this site and are pretty sensitive.

I will be cautious next time I post, for your sake.

Now since you are not here to help me with my troubles, I assume you will not need to post on my thread again.

Thanks for your great information!

You may have to further expand on the graph and its purpose; I suppose it reflects a vibration level at a predetermined position of the wheel and you wish to average the measurements at the predetermined wheel position?

I see the the negative zero on the graph; I'm unsure how one could have negative vibration at the negative zero wheel position; is this the err your speak of?

Thanks for the reply JMeller,

The graph shows a vibration level vs a wheel position.

The negative zero crossing point is the point at which I use to show where the compensation weight needs to be added.

The zero point on the graph is the static value of the accelerometer, so the vibration may be higher or lower depending on where the wheel is when the vibration occurs.

I think that I need to take the wheel position points at which the vibration wave travels through the zero line, and average the wheel position to give me the best compensation point. I may end up having to average out the sine wave instead, and use a single wheel position point. I think one or the other will work fine for what I am doing. But as far as the programming goes, I am unaware which will be more effective, and am unaware how I would achieve this.

I will post the program so you can see how I get this wave.

If there is anything else I can provide you, I am happy to do so.


#include <Wire.h>

byte DEVICE_ADDRESS = 0x53; //This address is fixed for the board we use because pin 12 is fixed to GND

byte POWER_CTRL = 0x2D;    //Power Control Register
byte DATA_FORMAT = 0x31;   //Data Format & Measurement Range Register

byte DATAX0 = 0x32;        //X-Axis Data 0
byte DATAX1 = 0x33;        //X-Axis Data 1
byte DATAY0 = 0x34;        //Y-Axis Data 0
byte DATAY1 = 0x35;        //Y-Axis Data 1

byte values[10]; 
int x,y;
int encoder0Pos;

void setup() {

  Wire.begin();    //Initiate the Wire library and join the I2C bus as a master. This is called only once.
   DDRB = B00000000; // set ports to inputs
   DDRD = B00000000; // set ports to inputs
  writeRegister(DEVICE_ADDRESS, DATA_FORMAT, 0x01); //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the register.
  writeRegister(DEVICE_ADDRESS, POWER_CTRL, 0x08); //Put the ADXL345 into Measurement Mode by writing the value 0x08 to the register. 
void loop() {
readRegister(DEVICE_ADDRESS, DATAX0, 6, values); 

y = ((int)values[3]<<8)|(int)values[2];
//y = map(y, -150, 150, 0, 255);

analogWrite(5, y);
Serial.print(y, DEC);
Serial.println(PINB, DEC);
void writeRegister(byte device, byte registerAddress, byte value) {
  Wire.beginTransmission(device);    //Start transmission to device
  Wire.write(registerAddress);       //Specify the address of the register to be written to
  Wire.write(value);                 //Send the value to be writen to the register
  Wire.endTransmission();            //End transmission 
void readRegister(byte device, byte registerAddress, int numBytes, byte *values) {
  byte address = 0x80|registerAddress;
  if (numBytes > 1) address = address|0x40;
  Wire.requestFrom(device, numBytes);  //Request 6 bytes from device
  int i = 0;
  while (Wire.available()) {          //Device may send less than requested
    values[i] =;          //Receive a byte from device and put it into the buffer

I'm not afraid to say it - the posted code is beyond my novice level. Perhaps one, or more, of the seasoned coders could point you in the correct direction - while I sit idly by and learn.

But as far as the programming goes, I am unaware which will be more effective, and am unaware how I would achieve this.

Generally speaking as a layman, I would think one would determine the desired resolution; store values every 10 degrees, every 5 degrees, all 360 degrees. Next, I would determine the maximum amount of revolutions before transmitting the averaged values. Once those factors are determined, begin tossing the values into an array (size determined by resolution); begin averaging the two numbers after wheel position 2; store new value into array slot; transmit the data on the determined revolution count setting; reset revolution count back to zero.

As previously stated - layman's view.