magnetic encoder accumulation into new value

I have a magnetic encoder that I can read values in the range of 0 to 1024. I need a way to be able to accumulate this value into a new value for example 2 rotations would be 2048 or -2048. I'm using a serial output variable to set this new position but cant seem to get my head around how I might tell it to do so. The attached code is working for the range in which I have mapped 1024 to 360. I want to use this accumulating value to be able to keep track of the position even if i rotate many times.

Most of the important things are in
void loop_sv4()

////////////////////// as5040
#include <PWM.h>

//AS5040 stuff
const int clockPin = 7; //output to clock
const int CSnPin = 6; //output to chip select
const int inputPin = 2; //read AS5040
int inputstream = 0; //one bit read from pin
long packeddata = 0; //two bytes concatenated from inputstream
long angle = 0; //holds processed angle value
long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info
long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info
long statusbits; //holds status/error information
int DECn; //bit holding decreasing magnet field error data
int INCn; //bit holding increasing magnet field error data
int OCF; //bit holding startup-valid bit
int COF; //bit holding cordic DSP processing error data
int LIN; //bit holding magnet field displacement error data
int debug = 0; //SET THIS TO 0 TO DISABLE PRINTING OF ERROR CODES
int shortdelay = 1; // this is the microseconds of delay in the data clock
int rotations = 0;  //how many times have I spun around
int overallpostion = 0;  //count rotations plus postions into a new value

//PID stuff
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

// Serial for VVVV
String readString;

//PWM fast
int ENA = 9;//fast PWM
int IN1 = 12;
int IN2 = 13;
int32_t frequency = 16000; //frequency (in Hz)


void setup_sv4() 
{
  Serial.begin(115200);
  InitTimersSafe(); 
  bool success = SetPinFrequencySafe(ENA, frequency);
  pinMode (ENA, OUTPUT);
  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
  //Serial.println("V4_Arduino_L298N_AS5040");//track what I have loaded
  
}

void setup()
{
  Serial.begin(9600);
  pinMode(clockPin, OUTPUT); // SCK
  pinMode(CSnPin, OUTPUT); // CSn -- has to toggle high and low to signal chip to start data transfer
  pinMode(inputPin, INPUT); // SDA
  
  setup_sv4();
}
void loop_sv4() {

  if (Serial.available())  
  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == 'a') 
	{
		if (readString.length() >0) 
		{
			int SerialInput = readString.toInt();  //convert readString into a number
                        int Xaxis = angle;//magnet position
                        int DiffLeft = SerialInput - Xaxis;
                        int DiffRight = Xaxis - SerialInput;
                        //int BreakL = 1;
                        //int BreakR = 1;
                     
                        //if (SerialInput > Xaxis && DiffLeft > BreakL) //> <
                        if (SerialInput > Xaxis) //> 
                                            {
			                     
                                             digitalWrite (IN1, HIGH);
                                             digitalWrite (IN2, LOW);
                                             int Lspd = map(DiffLeft, 0, 360, 404, 490);
                                             pwmWrite  (ENA, (Lspd) );
                                             Serial.println(DiffLeft, DEC);
                                             }
                        //f (DiffRight > BreakR)
                        else
                        {
                        digitalWrite (IN1, LOW);
                        digitalWrite (IN2, HIGH);
                        int Rspd = map(DiffRight, 0, 360, 404, 490);
                        pwmWrite  (ENA, (Rspd) );
                        readString=""; //clears variable for new input
                        Serial.println(DiffRight, DEC);
                       
                        }
                        Serial.println(angle, DEC);
                        
                         
		}
	}  
    else if (c == 'b') 
	{

		if (readString.length() >0) 
		{
			int n = readString.toInt();  //convert readString into a number
			readString=""; //clears variable for new input
		}
	}  	
    else if (c == 'c') 
	{

		if (readString.length() >0) 
		{
			int n = readString.toInt();  //convert readString into a number
			readString=""; //clears variable for new input
		}
	}  	
	else 
	{     
		/// be sure this value is >= '0' && <= '9'
		readString += c; //makes the string readString
	}
  }
}



void loop()
{
  loop_sv4();
// CSn needs to cycle from high to low to initiate transfer. Then clock cycles. As it goes high
// again, data will appear on sda
  digitalWrite(CSnPin, HIGH); // CSn high
  digitalWrite(clockPin, HIGH); // CLK high
  delay(shortdelay);// time between readings
  digitalWrite(CSnPin, LOW); // CSn low: start of transfer
  delayMicroseconds(shortdelay); // delay for chip initialization
  digitalWrite(clockPin, LOW); // CLK goes low: start clocking
  delayMicroseconds(shortdelay); // hold low
  for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin
  {
    digitalWrite(clockPin, HIGH); //clock goes high
    delayMicroseconds(shortdelay); //
    inputstream =digitalRead(inputPin); // read one bit of data from pin
    packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value
    digitalWrite(clockPin, LOW);
    delayMicroseconds(shortdelay); // end of one clock cycle
  }

  angle = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle.
  angle = (angle >> 6); // shift 16-digit angle right 6 digits to form 10-digit value
  angle = angle * 0.3515; // angle * (360/1024) == actual degrees
  //Serial.print("angle: "); // and, finally, print it.
  //Serial.println(angle, DEC);

  if (debug)
  {
    statusbits = packeddata & statusmask;
    DECn = statusbits & 2; // goes high if magnet moved away from IC
    INCn = statusbits & 4; // goes high if magnet moved towards IC
    LIN = statusbits & 8; // goes high for linearity alarm
    COF = statusbits & 16; // goes high for cordic overflow: data invalid
    OCF = statusbits & 32; // this is 1 when the chip startup is finished.
    if (DECn && INCn) { Serial.println("magnet moved out of range"); }
    else
    {
      if (DECn) { Serial.println("magnet moved away from chip"); }
      if (INCn) { Serial.println("magnet moved towards chip"); }
    }
    if (LIN) { Serial.println("linearity alarm: magnet misaligned? Data questionable."); }
    if (COF) { Serial.println("cordic overflow: magnet misaligned? Data invalid."); }
  }

  packeddata = 0; // reset both variables to zero so they don't just accumulate
  //angle = 0;
  
  
}

Wouldn't it be easier to read the angular position direct and count revolutions?
Because due east is the same no matter how many times the magnet turns.

Also I hope that thing didn't cost too much. A less than $2 linear Hall sensor can
give you the basic analog data without the frills which decent code (and possibly
needing a cheap trim pot) can provide anyway.

Put over the center of a steadily turning bar magnet it will read low to high in
a sine wave pattern. Your code would have to interpret that as the data will go
from 0 to 1023 in 180 degrees (say north pole to south pole, could be the other
way) and the 1023 to 0 for the other 180 degrees, which you would have to keep
track of in your code ie provide your own frills.

They are much easier to use as joystick sensors since joystick axes don't turn 180.

And guess what's at the heart of that board anyway?

the as5040 I got as samples and is working great so far..but its more of an issue for me on how to code the counts and set the position for multiple rotations..so I want it to go to postion 4000 which is a few rotations..how would I tell it too based on the fact that i only have 0 to 1024 plus a count of the rotation...how would i et that point to go beyond the 1024.

For one, I believe that you should only see 0-1023 which is 10 bits for 1024 positions.
It is like a day has 24 hours and 24-hour time starts at midnight 00:00:00 and ends at 23:59:59.

So if the board doesn't tell you when you went full circle, you need to count a +rotation when the angle goes from very high value to low (like 1020 to 10... you may not see every step especially if the magnet turns fast) or -rotation when the angle goes from low to high.

Knowing rotations and 0-1023 angle the number you want is rotations x 1024 + angle.

I'm not going to write the code for you, but I'd do it like this:

Record the previous value of the encoder 0 .. 1023.

Subtract the old from the new to determine how many units the position has moved. If the difference is more than 512 then subtract 1024 from it. If the difference is less than -512 then add 1024 to it. This handles the case where the encoder has jumped by a large amount, and also when it crosses zero in either direction. (The value zero means the encoder has not moved.)

Add the resulting value to a global counter which accumulates the total number of steps moved.

Save the new position as the previous position for next time.

Ok im starting to get the basics of the idea, however where is the best place an if statement to calculate the old vs new position. If I put it in my main loop then the angle position is going to be the same so it will always return 0. I cant quite get my head around that.

The magnet always puts out an absolute value each time my void loop_sv4(); function runs then I compare the serial input value with the encoder position to determine how fast the PWM should run(which works)..but still how to store the read position of the encoder to the newly read position of the encoder is a bit baffling

i did try and write something but still need some pointers of how to actually get it to read and store those difference values..here is what I have so far but it just returns 0 for the difference.

 ReadEncoder = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle.
  ReadEncoder = (ReadEncoder >> 6); // shift 16-digit angle right 6 digits to form 10-digit value
  
  Position = ReadEncoder;
  PreviousEncoder = Position;
  Encoder = ReadEncoder;
  difference = Position - PreviousEncoder;
  
             if (difference < 512){
             Globaladd = difference - 1024;}
             else if (difference > 512){
             Globaladd = difference + 1024;}
             
 GlobalPosition = GlobalPosition + Globaladd;
Position = ReadEncoder;     //Suppose ReadEncoder has value X, now Position has a value of X
  PreviousEncoder = Position;       //Now PreviousEncoder has a value of X
  Encoder = ReadEncoder;           //Now Encoder has a value of X
  difference = Position - PreviousEncoder;  //difference = X - X which for for any value of X, ie zero

yep I can see its not doing anything..maybe there is a way to store this value outside this loop somehow any pointers?

GoForSmoke:
Put over the center of a steadily turning bar magnet it will read low to high in
a sine wave pattern.

Not a perfect sine wave, not when close to the magnet. Might limit the precision. Also magnetic
interference from nearby currents can be an issue without magnetic shielding.

The Austria Microsystems datasheets don't claim that great a linearity BTW - but they use a disc
shaped small magnet.

like I say the sensor itself works fine..any slight linearity errors don't both this application as its on gear reduction that it becomes barley noticeable..my problem is setting up the code to accumulate the value of the 0 -1023 positions it gives out..

carbon_adam:
i did try and write something but still need some pointers of how to actually get it to read and store those difference values..here is what I have so far but it just returns 0 for the difference.

Since you have only posted a code fragment we can't see how those variables are declared. The cumulative step counter and the variable holding the previous position, both need to be global or static variables. (The other variables can be temporary local variables if you like.)

////////////////////// as5040
#include <PWM.h>

//AS5040 stuff
const int clockPin = 7; //output to clock
const int CSnPin = 6; //output to chip select
const int inputPin = 2; //read AS5040
int inputstream = 0; //one bit read from pin
long packeddata = 0; //two bytes concatenated from inputstream
long ReadEncoder = 0; //holds processed angle value
long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info
long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info
long statusbits; //holds status/error information
int DECn; //bit holding decreasing magnet field error data
int INCn; //bit holding increasing magnet field error data
int OCF; //bit holding startup-valid bit
int COF; //bit holding cordic DSP processing error data
int LIN; //bit holding magnet field displacement error data
int debug = 0; //SET THIS TO 0 TO DISABLE PRINTING OF ERROR CODES
int shortdelay = 1; // this is the microseconds of delay in the data clock
int longdelay = 100;
//int rotations = 0;  //how many times have I spun around
//int overallpostion = 0;  //count rotations plus postions into a new value
//int global_counter = 0;
int PreviousEncoder = 0;
int Position = 0;
int Encoder = 0;
int difference = 0;
int Globaladd = 0;
long GlobalPosition = 0;
// Serial for VVVV
String readString;

//PWM fast
int ENA = 9;//fast PWM
int IN1 = 12;
int IN2 = 13;
int32_t frequency = 16000; //frequency (in Hz)


void setup_sv4() 
{
  Serial.begin(115200);
  InitTimersSafe(); 
  bool success = SetPinFrequencySafe(ENA, frequency);
  pinMode (ENA, OUTPUT);
  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
  //Serial.println("V4_Arduino_L298N_AS5040");//track what I have loaded
  
}

void setup()
{
  Serial.begin(9600);
  pinMode(clockPin, OUTPUT); // SCK
  pinMode(CSnPin, OUTPUT); // CSn -- has to toggle high and low to signal chip to start data transfer
  pinMode(inputPin, INPUT); // SDA
  
  setup_sv4();
}
void loop_sv4() {

  if (Serial.available())  
  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == 'a') 
	{
		if (readString.length() >0) 
		{
			int SerialInput = readString.toInt();  //convert readString into a number
                        int Xaxis = ReadEncoder;//magnet position
                     //   Serial.print("global_counter: "); // and, finally, print it.
                       // Serial.println(global_counter, DEC);
                        int DiffLeft = SerialInput - Xaxis;
                        int DiffRight = Xaxis - SerialInput;
                        
                        if (SerialInput > Xaxis) 
                                            {
                                             digitalWrite (IN1, HIGH);
                                             digitalWrite (IN2, LOW);
                                             int Lspd = map(DiffLeft, 0, 1023, 404, 490);
                                             pwmWrite  (ENA, (Lspd) );
                                           //  Serial.println(DiffLeft, DEC);
                                             }
                       
                        else
                        {
                        digitalWrite (IN1, LOW);
                        digitalWrite (IN2, HIGH);
                        int Rspd = map(DiffRight, 0, 1023, 404, 490);
                        pwmWrite  (ENA, (Rspd) );
                        readString=""; //clears variable for new input
                      //  Serial.println(DiffRight, DEC);
                       
                        }
                       // Serial.println(ReadEncoder, DEC);
                        
                         
		}
	}  
    else if (c == 'b') 
	{

		if (readString.length() >0) 
		{
			int n = readString.toInt();  //convert readString into a number
			readString=""; //clears variable for new input
		}
	}  	
    else if (c == 'c') 
	{

		if (readString.length() >0) 
		{
			int n = readString.toInt();  //convert readString into a number
			readString=""; //clears variable for new input
		}
	}  	
	else 
	{     
		/// be sure this value is >= '0' && <= '9'
		readString += c; //makes the string readString
	}
  }
}



void loop()
{
  loop_sv4();
// CSn needs to cycle from high to low to initiate transfer. Then clock cycles. As it goes high
// again, data will appear on sda
  digitalWrite(CSnPin, HIGH); // CSn high
  digitalWrite(clockPin, HIGH); // CLK high
  delay(shortdelay);// time between readings
  digitalWrite(CSnPin, LOW); // CSn low: start of transfer
  delayMicroseconds(shortdelay); // delay for chip initialization
  digitalWrite(clockPin, LOW); // CLK goes low: start clocking
  delayMicroseconds(shortdelay); // hold low
  for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin
  {
    digitalWrite(clockPin, HIGH); //clock goes high
    delayMicroseconds(shortdelay); //
    inputstream =digitalRead(inputPin); // read one bit of data from pin
    packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value
    digitalWrite(clockPin, LOW);
    delayMicroseconds(shortdelay); // end of one clock cycle
  }

  ReadEncoder = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle.
  ReadEncoder = (ReadEncoder >> 6); // shift 16-digit angle right 6 digits to form 10-digit value
  
  Position = ReadEncoder;
  PreviousEncoder = Position;
  Encoder = ReadEncoder;
  difference = Position - PreviousEncoder;
  
             if (difference == 0)
             {
             Globaladd = 0;}
             else if (difference < 512){
             Globaladd = difference - 1024;}
             else if (difference > 512){
             Globaladd = difference + 1024;}
             
 GlobalPosition = GlobalPosition + Globaladd;
                                      
 //Serial.print("difference: "); // and, finally, print it.
 //Serial.println(difference, DEC);
  
// Serial.print("GlobalPosition: "); // and, finally, print it.
 Serial.println(GlobalPosition, DEC);

 // angle = angle * 0.3515; // angle * (360/1024) == actual degrees
  //Serial.print("angle: "); // and, finally, print it.
  //Serial.println(angle, DEC);

  if (debug)
  {
    statusbits = packeddata & statusmask;
    DECn = statusbits & 2; // goes high if magnet moved away from IC
    INCn = statusbits & 4; // goes high if magnet moved towards IC
    LIN = statusbits & 8; // goes high for linearity alarm
    COF = statusbits & 16; // goes high for cordic overflow: data invalid
    OCF = statusbits & 32; // this is 1 when the chip startup is finished.
    if (DECn && INCn) { Serial.println("magnet moved out of range"); }
    else
    {
      if (DECn) { Serial.println("magnet moved away from chip"); }
      if (INCn) { Serial.println("magnet moved towards chip"); }
    }
    if (LIN) { Serial.println("linearity alarm: magnet misaligned? Data questionable."); }
    if (COF) { Serial.println("cordic overflow: magnet misaligned? Data invalid."); }
  }

  packeddata = 0; // reset both variables to zero so they don't just accumulate
  //angle = 0;
  
  
}

UKHeliBob:

Position = ReadEncoder;     //Suppose ReadEncoder has value X, now Position has a value of X

PreviousEncoder = Position;       //Now PreviousEncoder has a value of X
  Encoder = ReadEncoder;           //Now Encoder has a value of X
  difference = Position - PreviousEncoder;  //difference = X - X which for for any value of X, ie zero

I think that Bob is showing you where you jumped the shark.

Try not copying the current position value in the previous position until after you calculate the difference. You might get better results then.

Ok so thanks for that managed to get a valid difference using the below section. I tried to make the function calculate a global value but seems I am not really getting something right there..any more pointers?

//All variables are global
  Position = ReadEncoder; //get current position of sensor
  difference = Position - PreviousEncoder;  //first time round its == 0          
         
         
         if (difference > 512 && difference != 0) //condition 1
             {Globaladd = difference - 1024;}
             
             if (difference < -512 && difference != 0)
                  {Globaladd = difference + 1024;}
             
                      else Globaladd = 0;
                      
GlobalPosition = GlobalPosition + Globaladd;

PreviousEncoder = Position;

 Serial.print("Position: "); 
 Serial.println(Position, DEC);
 Serial.print("PreviousEncoder: "); 
 Serial.println(PreviousEncoder, DEC);
 Serial.print("difference: "); 
 Serial.println(difference, DEC);

carbon_adam:
any more pointers?

         if (difference > 512 && difference != 0) //condition 1

{Globaladd = difference - 1024;}
           
            if (difference < -512 && difference != 0)
                 {Globaladd = difference + 1024;}
           
                     else Globaladd = 0;
                     
GlobalPosition = GlobalPosition + Globaladd;




If difference is > 512, how can it be 0? 
If -512 < difference < 512 then it doesn't count? Because if difference is in that range you zero Globaladd.

Your structure with those if() statements really does not help. Lay it out more clearly since either way compiles the same but the way it is perhaps lets you not see what you're asking.



if (difference > 512 && difference != 0) //condition 1
        {
            Globaladd = difference - 1024;
        }
           
        if (difference < -512 && difference != 0)
        {
            Globaladd = difference + 1024;
        }
        else
        {
            Globaladd = 0;
        }




Do you see that even if difference is > 512 that the next if-else will make Globaladd zero? Perhaps...



if ( difference > 512 ) //condition 1
        {
            Globaladd = difference - 1024;
        }
        else if ( difference < -512 )
        {
            Globaladd = difference + 1024;
        }
        else
        {
            Globaladd = difference;
        }




I spread things out to make for easier viewing ( harder to mistake a '(' or '!' with a '1', and other what's-that's that aren't always caught at a glance ), less mistakes about indent levels and what is inside of what, and not for 'aesthetics', ie 'looks'. Having more lines on screen is nice but when they make things less clear then it only makes bugs easier to gloss over and takes longer to read properly.

Thanks GoForSmoke that did the trick:) I posted the entire code should someone else want to repeat or expand on using the hardware and software I have used.

The serial input I got from a program called VVVV and if anyone is interested in the patch I can send it to them.
The motor driver I used was the L298n along with the higher frequency PWM.lib and the belt drive I have its almost completely silent..so yay! (because this is for a type of electronic instrument).

Right now I deal with a fixed set of values between 0 - 5000 so that I can easily map the difference between the serial and the global position to use as an intensity factor for the PWM. Im looking to change this into a percentage value of the difference(not sure how but Ill poke around on the forums).

Thanks everyone for their help so far I really appreciate.

//AS5040 + VVVV over serial + L298N + PWM.lib
#include <PWM.h>

//AS5040 stuff
const int clockPin = 7; //output to clock
const int CSnPin = 6; //output to chip select
const int inputPin = 2; //read AS5040
int inputstream = 0; //one bit read from pin
long packeddata = 0; //two bytes concatenated from inputstream
long ReadEncoder = 0; //holds processed angle value
long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info
long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info
long statusbits; //holds status/error information
int DECn; //bit holding decreasing magnet field error data
int INCn; //bit holding increasing magnet field error data
int OCF; //bit holding startup-valid bit
int COF; //bit holding cordic DSP processing error data
int LIN; //bit holding magnet field displacement error data
int debug = 0; //SET THIS TO 0 TO DISABLE PRINTING OF ERROR CODES
int shortdelay = 1; // this is the microseconds of delay in the data clock
int longdelay = 100;
//int rotations = 0;  //how many times have I spun around
//int overallpostion = 0;  //count rotations plus postions into a new value
//int global_counter = 0;
int PreviousEncoder = 0;
int Position = 0;
int Encoder = 0;
int difference = 0;
int Globaladd = 0;
long GlobalPosition = 0;
// Serial for VVVV
String readString;
int Predifference = 0;
//PWM fast
int ENA = 9;//fast PWM
int IN1 = 12;
int IN2 = 13;
int32_t frequency = 16000; //frequency (in Hz)


void setup_sv4() 
{
  Serial.begin(115200);
  InitTimersSafe(); 
  bool success = SetPinFrequencySafe(ENA, frequency);
  pinMode (ENA, OUTPUT);
  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
  //Serial.println("V4_Arduino_L298N_AS5040");//track what I have loaded
  
}

void setup()
{
  Serial.begin(9600);
  pinMode(clockPin, OUTPUT); // SCK
  pinMode(CSnPin, OUTPUT); // CSn -- has to toggle high and low to signal chip to start data transfer
  pinMode(inputPin, INPUT); // SDA
  
  setup_sv4();
}
void loop_sv4() {

  if (Serial.available())  
  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == 'a') 
	{
		if (readString.length() >0) 
		        {
			int SerialInput = readString.toInt();  //convert readString into a number
                        int Xaxis = GlobalPosition; //counted rotations and postion
                        int DiffLeft = SerialInput - Xaxis;
                        int DiffRight = Xaxis - SerialInput;
                      
                        if (SerialInput > Xaxis)
                        {
                        digitalWrite (IN1, HIGH);
                        digitalWrite (IN2, LOW);
                        int Lspd = map(DiffLeft, 0, 5000, 404, 490);
                        pwmWrite  (ENA, (Lspd) );
                        Serial.print("Lspd: ");
                        Serial.println(DiffLeft, DEC);
                        }
                        else //if (DiffRight > 50)
                        {
                        digitalWrite (IN1, LOW);
                        digitalWrite (IN2, HIGH);
                        int Rspd = map(DiffRight, 0, 5000, 404, 490);
                        pwmWrite  (ENA, (Rspd) );
                        Serial.print("Rspd: ");
                        Serial.println(DiffRight, DEC);
                        readString=""; //clears variable for new input
                        }
     
		}
	}  
    else if (c == 'b') 
	{

		if (readString.length() >0) 
		{
			int n = readString.toInt();  //convert readString into a number
			readString=""; //clears variable for new input
		}
	}  	
    else if (c == 'c') 
	{

		if (readString.length() >0) 
		{
			int n = readString.toInt();  //convert readString into a number
			readString=""; //clears variable for new input
		}
	}  	
	else 
	{     
		/// be sure this value is >= '0' && <= '9'
		readString += c; //makes the string readString
	}
  }
}



void loop()
{
  loop_sv4();
// CSn needs to cycle from high to low to initiate transfer. Then clock cycles. As it goes high
// again, data will appear on sda
  digitalWrite(CSnPin, HIGH); // CSn high
  digitalWrite(clockPin, HIGH); // CLK high
  delay(shortdelay);// time between readings
  digitalWrite(CSnPin, LOW); // CSn low: start of transfer
  delayMicroseconds(shortdelay); // delay for chip initialization
  digitalWrite(clockPin, LOW); // CLK goes low: start clocking
  delayMicroseconds(shortdelay); // hold low
  for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin
  {
    digitalWrite(clockPin, HIGH); //clock goes high
    delayMicroseconds(shortdelay); //
    inputstream =digitalRead(inputPin); // read one bit of data from pin
    packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value
    digitalWrite(clockPin, LOW);
    delayMicroseconds(shortdelay); // end of one clock cycle
  }

  ReadEncoder = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle.
  ReadEncoder = (ReadEncoder >> 6); // shift 16-digit angle right 6 digits to form 10-digit value
  Position = ReadEncoder; //get current position of sensor
  difference = Position - PreviousEncoder;  //first time round its == 0          
         
         
         if ( difference > 512 ) //condition 1
         {
             Globaladd = difference - 1024;
         }
         else if ( difference < -512 )
         {
             Globaladd = difference + 1024;
         }
         else 
         {
             Globaladd = difference;
         }
                      
 //Serial.print("Globaladd: "); // and, finally, print it.
// Serial.println(Globaladd, DEC);                     
                      
GlobalPosition = GlobalPosition + Globaladd;

PreviousEncoder = Position;

 //Serial.print("Position: "); // and, finally, print it.
// Serial.println(Position, DEC);
// Serial.print("PreviousEncoder: "); // and, finally, print it.
 //Serial.println(PreviousEncoder, DEC);
 //Serial.print("difference: "); // and, finally, print it.
 //Serial.println(difference, DEC);
 //Serial.print("GlobalPosition: "); // and, finally, print it.
 //Serial.println(GlobalPosition, DEC);
  if (debug)
  {
    statusbits = packeddata & statusmask;
    DECn = statusbits & 2; // goes high if magnet moved away from IC
    INCn = statusbits & 4; // goes high if magnet moved towards IC
    LIN = statusbits & 8; // goes high for linearity alarm
    COF = statusbits & 16; // goes high for cordic overflow: data invalid
    OCF = statusbits & 32; // this is 1 when the chip startup is finished.
   // if (DECn && INCn) { Serial.println("magnet moved out of range"); }
    //else
    {
     // if (DECn) { Serial.println("magnet moved away from chip"); }
    //  if (INCn) { Serial.println("magnet moved towards chip"); }
    }
   // if (LIN) { Serial.println("linearity alarm: magnet misaligned? Data questionable."); }
   // if (COF) { Serial.println("cordic overflow: magnet misaligned? Data invalid."); }
  }

  packeddata = 0; // reset both variables to zero so they don't just accumulate
  //angle = 0;
  
  
}

hello
i found your posts because i try to build a anemometer with a as5040.. my problem is quite the same, i cant count them rotations of my magnet... i can get the exact angle (for winddirection but i'm not able to meassure themwindspeed...
maybe someone has found out how to count themrelevations? the next problem, i'm a hobby-tinker and not a programmer so i don't really understand all the codes.. so maybe you can help me a little bit ???
thanks...

here is my code for the angle...

#include <SPI.h>
#include <MySensor.h>

//const int ledPin = 13; //LED connected to digital pin 13
const int clockPin = 5; //output to clock
const int CSnPin = 4; //output to chip select
const int inputPin = 6; //read AS5040

int inputstream = 0; //one bit read from pin
long packeddata = 0; //two bytes concatenated from inputstream
long angle = 0; //holds processed angle value
long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info
long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info
long statusbits; //holds status/error information
int DECn; //bit holding decreasing magnet field error data
int INCn; //bit holding increasing magnet field error data
int OCF; //bit holding startup-valid bit
int COF; //bit holding cordic DSP processing error data
int LIN; //bit holding magnet field displacement error data
int debug = 0; //SET THIS TO 0 TO DISABLE PRINTING OF ERROR CODES
int shortdelay = 1000; // this is the microseconds of delay in the data clock
int longdelay =1000; // this is the milliseconds between readings
#define CHILD_ID_DIR 0
//#define INTERRUPT inputPin
MySensor gw;
MyMessage msgDIR(CHILD_ID_DIR, V_DIRECTION);

void setup()
{
gw.begin(NULL, AUTO, true, AUTO);
Serial.begin(250000);
// pinMode(ledPin, OUTPUT); // visual signal of I/O to chip
pinMode(clockPin, OUTPUT); // SCK
pinMode(CSnPin, OUTPUT); // CSn -- has to toggle high and low to signal chip to start data transfer
pinMode(inputPin, INPUT); // SDA

// Send the Sketch Version Information to the Gateway
gw.sendSketchInfo("Winddirection", "1.0");
// Register all sensors to gw (they will be created as child devices)
gw.present(CHILD_ID_DIR, S_WIND);
}

void loop()
{
// CSn needs to cycle from high to low to initiate transfer. Then clock cycles. As it goes high
// again, data will appear on sda
digitalWrite(CSnPin, HIGH); // CSn high
digitalWrite(clockPin, HIGH); // CLK high
delay(longdelay);// time between readings
// digitalWrite(ledPin, HIGH); // signal start of transfer with LED
digitalWrite(CSnPin, LOW); // CSn low: start of transfer
delayMicroseconds(shortdelay); // delay for chip initialization
digitalWrite(clockPin, LOW); // CLK goes low: start clocking
delayMicroseconds(shortdelay); // hold low
for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin
{
digitalWrite(clockPin, HIGH); //clock goes high
delayMicroseconds(shortdelay); //
inputstream =digitalRead(inputPin); // read one bit of data from pin
//Serial.print(inputstream, DEC);
packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value
digitalWrite(clockPin, LOW);
delayMicroseconds(shortdelay); // end of one clock cycle
}
// digitalWrite(ledPin, LOW); // signal end of transmission
angle = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle.
angle = (angle >> 6); // shift 16-digit angle right 6 digits to form 10-digit value
angle = angle * 0.3515; // angle * (360/1024) == actual degrees
Serial.print("angle: "); // and, finally, print it.
Serial.println(angle, DEC);
if (debug)
{
statusbits = packeddata & statusmask;
DECn = statusbits & 2; // goes high if magnet moved away from IC
INCn = statusbits & 4; // goes high if magnet moved towards IC
LIN = statusbits & 8; // goes high for linearity alarm
COF = statusbits & 16; // goes high for cordic overflow: data invalid
OCF = statusbits & 32; // this is 1 when the chip startup is finished.
if (DECn && INCn) { Serial.println("magnet moved out of range"); }
else
{
if (DECn) { Serial.println("magnet moved away from chip"); }
if (INCn) { Serial.println("magnet moved towards chip"); }
}
if (LIN) { Serial.println("linearity alarm: magnet misaligned? Data questionable."); }
if (COF) { Serial.println("cordic overflow: magnet misaligned? Data invalid."); }
}
float V_DIRECTION = angle;
gw.send(msgDIR.set(V_DIRECTION, DEC));
packeddata = 0; // reset both variables to zero so they don't just accumulate
angle = 0;
gw.process();
//gw.sleep(INTERRUPT,CHANGE);
gw.sleep(longdelay);
}

Do you have two of these units? One to measure wind direction and one to measure wind speed?

My understanding of the data sheet is that the AS5040 should have a standard A/B quadrature output on pins 3 and 4 as well as an index pulse on pin 6. You should be using it like an incremental rotary encoder for wind speed.

Check out this tutorial Arduino Playground - RotaryEncoders

good morning
right, i have one for the wind direction and obe for the speed..
ams sent me 3 pcs for sample and for free...
so...
i will have a look ar your link... thanks...