Invalid Conversion from uint8_t* to uint8_t fpermissive c++ - c++

I realize issue has been asked many times, but after reading many many similar questions I am still unable to understand and solve this issue. I am a novice coder and am still learning, and for many days i have been unable to solve this issue.
I am using a demo code library from arduino and trying to compile it in c++ Atmel Studio 7 (compiling for a custom board i made based on ATSAMD21). Here is my relevant code (removed all unrelated parts):
#include <Arduino.h>
#include <Wire.h>
#include "Kalman.h" // Source: https://github.com/TKJElectronics/KalmanFilter
//Beginning of Auto generated function prototypes by Atmel Studio
uint8_t i2cWrite(uint8_t registerAddress, uint8_t data, bool sendStop);
uint8_t i2cWrite(uint8_t registerAddress, uint8_t data, uint8_t length, bool sendStop);
uint8_t i2cRead(uint8_t registerAddress, uint8_t data, uint8_t nbytes);
//End of Auto generated function prototypes by Atmel Studio
#define RESTRICT_PITCH // Comment out to restrict roll to ±90deg instead - please read: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf
Kalman kalmanX; // Create the Kalman instances
Kalman kalmanY;
/* IMU Data */
double accX, accY, accZ;
double gyroX, gyroY, gyroZ;
int16_t tempRaw;
double gyroXangle, gyroYangle; // Angle calculate using the gyro only
double compAngleX, compAngleY; // Calculated angle using a complementary filter
double kalAngleX, kalAngleY; // Calculated angle using a Kalman filter
uint32_t timer;
uint8_t i2cData[14]; // Buffer for I2C data
// TODO: Make calibration routine
#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
// Required for Serial on Zero based boards
#define Serial SERIAL_PORT_USBVIRTUAL
#endif
void setup() {
Serial.begin(115200);
Wire.begin();
//TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz
i2cData[0] = 7; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz
i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
i2cData[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g
while (i2cWrite(0x19, *i2cData, 4, false)); // Write to all four registers at once
while (i2cWrite(0x6B, 0x01, true)); // PLL with X axis gyroscope reference and disable sleep mode
while (i2cRead(0x75, *i2cData, 1));
if (i2cData[0] != 0x68) { // Read "WHO_AM_I" register
Serial.print(F("Error reading sensor"));
while (1);
}
//delay(100); // Wait for sensor to stabilize
/* Set kalman and gyro starting angle */
while (i2cRead(0x3B, *i2cData, 6));
accX = (i2cData[0] << 8) | i2cData[1];
accY = (i2cData[2] << 8) | i2cData[3];
accZ = (i2cData[4] << 8) | i2cData[5];
// Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
// atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
// It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
double roll = atan2(accY, accZ) * RAD_TO_DEG;
double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
double roll = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif
kalmanX.setAngle(roll); // Set starting angle
kalmanY.setAngle(pitch);
gyroXangle = roll;
gyroYangle = pitch;
compAngleX = roll;
compAngleY = pitch;
timer = micros();
}
void loop() {
/* Update all the values */
while (i2cRead(0x3B, *i2cData, 14));
accX = ((i2cData[0] << 8) | i2cData[1]);
accY = ((i2cData[2] << 8) | i2cData[3]);
accZ = ((i2cData[4] << 8) | i2cData[5]);
tempRaw = (i2cData[6] << 8) | i2cData[7];
gyroX = (i2cData[8] << 8) | i2cData[9];
gyroY = (i2cData[10] << 8) | i2cData[11];
gyroZ = (i2cData[12] << 8) | i2cData[13];
double dt = (double)(micros() - timer) / 1000000; // Calculate delta time
timer = micros();
// Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
// atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
// It is then converted from radians to degrees
#ifdef RESTRICT_PITCH // Eq. 25 and 26
double roll = atan2(accY, accZ) * RAD_TO_DEG;
double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
double roll = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif
double gyroXrate = gyroX / 131.0; // Convert to deg/s
double gyroYrate = gyroY / 131.0; // Convert to deg/s
#ifdef RESTRICT_PITCH
// This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {
kalmanX.setAngle(roll);
compAngleX = roll;
kalAngleX = roll;
gyroXangle = roll;
} else
kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter
if (abs(kalAngleX) > 90)
gyroYrate = -gyroYrate; // Invert rate, so it fits the restriced accelerometer reading
kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);
#else
// This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
if ((pitch < -90 && kalAngleY > 90) || (pitch > 90 && kalAngleY < -90)) {
kalmanY.setAngle(pitch);
compAngleY = pitch;
kalAngleY = pitch;
gyroYangle = pitch;
} else
kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt); // Calculate the angle using a Kalman filter
if (abs(kalAngleY) > 90)
gyroXrate = -gyroXrate; // Invert rate, so it fits the restriced accelerometer reading
kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter
#endif
gyroXangle += gyroXrate * dt; // Calculate gyro angle without any filter
gyroYangle += gyroYrate * dt;
//gyroXangle += kalmanX.getRate() * dt; // Calculate gyro angle using the unbiased rate
//gyroYangle += kalmanY.getRate() * dt;
compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll; // Calculate the angle using a Complimentary filter
compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;
// Reset the gyro angle when it has drifted too much
if (gyroXangle < -180 || gyroXangle > 180)
gyroXangle = kalAngleX;
if (gyroYangle < -180 || gyroYangle > 180)
gyroYangle = kalAngleY;
uint32_t time = millis();
/* Print Data */
#if 1 // Set to 1 to activate
Serial.print(accX); Serial.print("\t");
Serial.print(accY); Serial.print("\t");
Serial.print(accZ); Serial.print("\t");
Serial.print(gyroX); Serial.print("\t");
Serial.print(gyroY); Serial.print("\t");
Serial.print(gyroZ); Serial.print("\t");
Serial.print(time); Serial.print("\t");
Serial.print("\t");
#endif
#if 0
Serial.print(roll); Serial.print("\t");
Serial.print(gyroXangle); Serial.print("\t");
Serial.print(compAngleX); Serial.print("\t");
Serial.print(kalAngleX); Serial.print("\t");
Serial.print("\t");
Serial.print(pitch); Serial.print("\t");
Serial.print(gyroYangle); Serial.print("\t");
Serial.print(compAngleY); Serial.print("\t");
Serial.print(kalAngleY); Serial.print("\t");
#endif
#if 1 // Set to 1 to print the temperature
Serial.print("\t");
double temperature = (double)tempRaw / 340.0 + 36.53;
Serial.print(temperature); Serial.print("\t");
#endif
Serial.print("\r\n");
//delay(2);
}
const uint8_t IMUAddress = 0x68; // AD0 is logic low on the PCB
const uint16_t I2C_TIMEOUT = 1000; // Used to check for errors in I2C communication
uint8_t i2cWrite(uint8_t registerAddress, uint8_t data, bool sendStop) {
return i2cWrite(registerAddress, &data, 1, sendStop); // INVALID CONVERSION ERROR HERE
}
uint8_t i2cWrite(uint8_t registerAddress, uint8_t *data, uint8_t length, bool sendStop) {
Wire.beginTransmission(IMUAddress);
Wire.write(registerAddress);
Wire.write(data, length);
uint8_t rcode = Wire.endTransmission(sendStop); // Returns 0 on success
if (rcode) {
Serial.print(F("i2cWrite failed: "));
Serial.println(rcode);
}
return rcode; // See: http://arduino.cc/en/Reference/WireEndTransmission
}
uint8_t i2cRead(uint8_t registerAddress, uint8_t *data, uint8_t nbytes) {
uint32_t timeOutTimer;
Wire.beginTransmission(IMUAddress);
Wire.write(registerAddress);
uint8_t rcode = Wire.endTransmission(false); // Don't release the bus
if (rcode) {
Serial.print(F("i2cRead failed: "));
Serial.println(rcode);
return rcode; // See: http://arduino.cc/en/Reference/WireEndTransmission
}
Wire.requestFrom(IMUAddress, nbytes, (uint8_t)true); // Send a repeated start and then release the bus after reading
for (uint8_t i = 0; i < nbytes; i++) {
if (Wire.available())
data[i] = Wire.read();
else {
timeOutTimer = micros();
while (((micros() - timeOutTimer) < I2C_TIMEOUT) && !Wire.available());
if (Wire.available())
data[i] = Wire.read();
else {
Serial.println(F("i2cRead timeout"));
return 5; // This error value is not already taken by endTransmission
}
}
}
return 0; // Success
}
The above code gives error in the i2cWrite function at line 195 Col 54:
invalid conversion from 'uint8_t* {aka unsigned char*}' to 'uint8_t {aka unsigned char}' -fpermissive
Note that i modified the above code first and added an *asterisk to i2cWrite/i2cRead array on lines 43, 46, 55, 83. If i don't add those then the same exact error on ALL those lines as well. Since the original code didn't have those *references maybe I wasn't supposed to add those pointers...?
I am trying to learn about pointers and references, but struggling. For the life of me i cannot understand how to solve this error. I've tried various & and * but for the life of me can't understand and correct this issue. I just cant seem to understand how/where my code is trying to assign a uint8_t* to uint8_t.
Per other topics, do i need to cast or use volatile or const to any of these variables? I don't think so but again i'm a beginner.
I'd be very grateful for anyone to point me in the right direction or help me understand a solution. In Arduino i can compile and run this code, but not in Atmel Studio. Any help is much appreciated.
EDIT: I've updated the code and removed the comments so that the error and line numbers match up with my post. Apologies for confusion on the line #s.

You need to declare the function before calling it.
In the definition of i2cWrite, it cannot see the declaration of the overload that receives a pointer as argument. Because of that, the compiler is assuming you are calling the function recursively, in which has a argument with wrong type.

This is a problem:
uint8_t i2cWrite(uint8_t registerAddress, uint8_t data, bool sendStop) {
return i2cWrite(registerAddress, &data, 1, sendStop); // Returns 0 on success
}
As shown by the first line, i2cWrite takes 3 arguments: uint8_t, uint8_t, and bool. But then you call it with 4 arguments: uint8_t, uint8_t *, int, bool.
Then after that you declare another function called i2cWrite that takes 4 arguments. This is not allowed .
It's hard to say but I'm guessing that you wanted these functions to have different names, the 3-argument one and the 4-argument one.

Thanks to both answers. The solution was simply my function prototypes at the very beginning were slightly different. The 2nd i2cWrite declaration was missing the derefernce *asterisk. That fixed it right up.

Related

Values of c++ array keep getting switched

I have an arduino program that runs a servo when it's at an odd angle, but after five seconds if still at that odd angle set it as the new center. the problem is that for some reason when I'm setting the angles of the current rotation to be the new center, the values get mixed up. Furthermore, the values of the center seem to be updating before the five seconds has even passed. I think this is something to do with the compiler. My code is here:
/*
Arduino and MPU6050 Accelerometer and Gyroscope Sensor Tutorial
by Dejan, https://howtomechatronics.com
*/
#include <Wire.h>
#include <Servo.h>
#define SERVO_PIN 9 //PWM pin that is connected to the servo
Servo demoServo; //create a servo object
int servoAngle = 0; //servo angle which can vary from 0 - 180
const int MPU = 0x68; // MPU6050 I2C address
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float rot[1];
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;
bool shake;
int shakeTime = 0;
float stablePos[1];
void setup() {
Serial.begin(19200);
Wire.begin(); // Initialize comunication
Wire.beginTransmission(MPU); // Start communication with MPU6050 // MPU=0x68
Wire.write(0x6B); // Talk to the register 6B
Wire.write(0x00); // Make reset - place a 0 into the 6B register
Wire.endTransmission(true); //end the transmission
demoServo.attach(SERVO_PIN);
delay(20);
stablePos[0] = 0;
stablePos[1] = 0;
rot[0] = 0;
rot[1] = 1;
}
void setIMU(float rot[])
{
// === Read acceleromter data === //
Wire.beginTransmission(MPU);
Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
//For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
// Calculating Roll and Pitch from the accelerometer data
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.93; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) - 4.23; // AccErrorY ~(-1.58)
// === Read gyroscope data === //
previousTime = currentTime; // Previous time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
Wire.beginTransmission(MPU);
Wire.write(0x43); // Gyro data first register address 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// Correct the outputs with the calculated error values
GyroX = GyroX + 0.43; // GyroErrorX ~(-0.56)
GyroY = GyroY + 0.63; // GyroErrorY ~(2)
GyroZ = GyroZ + 1.67; // GyroErrorZ ~ (-0.8)
// Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;
// Complementary filter - combine acceleromter and gyro angle values
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
rot[0] = pitch-10 > rot[0] || pitch+10 < rot[0] ? pitch : rot[0];
rot[1] = roll-10 > rot[1] || roll+10 < rot[1] ? roll : rot[1];
}
void loop() {
setIMU(rot);
Serial.print("STABLE AT:");
Serial.print(stablePos[0]);
Serial.print("/");
Serial.print(stablePos[1]);
Serial.print("\t CURRENTLY AT:");
Serial.print(rot[0]);
Serial.print("/");
Serial.println(rot[1]);
shake = (rot[0]>stablePos[0]+20 || rot[0]<stablePos[0]-20) ? true : (rot[1]>stablePos[1]+20 || rot[1]<stablePos[1]-20);
shakeTime = shake && shakeTime == 0 ? millis() + 5000 : shakeTime;
if (shakeTime < millis() && shakeTime != 0){
shakeTime = 0;
shake = false;
stablePos[0] = rot[0];
stablePos[1] = rot[1];
}
Serial.println(shake);
//Serial.println(shakeTime/1000);
demoServo.write(shake ? 180 : 0);
}
and the output of a test can be seen here:
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/0.00
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/0.00
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/-0.00
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/-0.14
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/-0.26
0
STABLE AT:0.00/0.00 CURRENTLY AT:0.00/0.05
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.41
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/-0.00
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.16
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.00
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/1.49
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/1.86
0
STABLE AT:0.00/10.98 CURRENTLY AT:10.98/0.00
0
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/0.63
1
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/2.57
1
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/2.70
1
STABLE AT:0.00/21.30 CURRENTLY AT:21.30/2.69
1
STABLE AT:0.00/31.95 CURRENTLY AT:31.95/2.56
1
STABLE AT:0.00/31.95 CURRENTLY AT:31.95/-0.00
1
STABLE AT:0.00/31.95 CURRENTLY AT:31.95/-0.00
1
as you can see, not only does the stable position update to 10.98 before the shake boolean gets set to two, but the placement is reversed as well.
float stablePos[1]; is an array of one element; the only valid index is stablePos[0]. By accessing stablePos[1], your program exhibits undefined behavior. Same with rot.

stereo ping pong delay c++

I have to create a stereo ping pong delay with these parameters.
• Delay Time (0 – 3000 milliseconds)
• Feedback (0 – 0.99)
• Wet / Dry Mix (0 – 1.0)
I have managed to implement the stereo in/out and the 3 parameters, but struggling with how to implement the ping pong. I have this code in the process block, but it only replays the left and right in the opposite channels once. Is there a simple way to loop this to reply over and over and not just once or have is this not the best way to implement ping pong. Any help would be great!
//ping pong implementation
for (int i = 0; i < buffer.getNumSamples(); i++)
{
// Reduce the amplitude of each sample in the block for the
// left and right channels
//channelDataLeft[i] = channelDataLeft[i] * 0.5;
// channelDataRight[i] = channelDataRight[i] * 0.25;
if (i % 2 == 1) //if i is odd this will play
{
// Calculate the next output sample (current input sample + delayed version)
float outputSampleLeft = (channelDataLeft[i] + (mix * delayDataLeft[readIndex]));
float outputSampleRight = (channelDataRight[i] + (mix * delayDataRight[readIndex]));
// Write the current input into the delay buffer along with the delayed sample
delayDataLeft[writeIndex] = channelDataLeft[i] + (delayDataLeft[readIndex] * feedback);
delayDataRight[writeIndex] = channelDataRight[i] + (delayDataRight[readIndex] * feedback);
// Increment read and write index, check to see if it's greater than buffer length
// if yes, wrap back around to zero
if (++readIndex >= delayBufferLength)
readIndex = 0;
if (++writeIndex >= delayBufferLength)
writeIndex = 0;
// Assign output sample computed above to the output buffer
channelDataLeft[i] = outputSampleLeft;
channelDataRight[i] = outputSampleRight;
}
else //if i is even then this will play
{
// Calculate the next output sample (current input sample + delayed version swapped around from if)
float outputSampleLeft = (channelDataLeft[i] + (mix * delayDataRight[readIndex]));
float outputSampleRight = (channelDataRight[i] + (mix * delayDataLeft[readIndex]));
// Write the current input into the delay buffer along with the delayed sample
delayDataLeft[writeIndex] = channelDataLeft[i] + (delayDataLeft[readIndex] * feedback);
delayDataRight[writeIndex] = channelDataRight[i] + (delayDataRight[readIndex] * feedback);
// Increment read and write index, check to see if it's greater than buffer length
// if yes, wrap back around to zero
if (++readIndex >= delayBufferLength)
readIndex = 0;
if (++writeIndex >= delayBufferLength)
writeIndex = 0;
// Assign output sample computed above to the output buffer
channelDataLeft[i] = outputSampleLeft;
channelDataRight[i] = outputSampleRight;
}
}
Not really sure why you have the modulo one and different behavior based on sample index. A ping-pong delay should have two delay buffers, one for each channel. The input of one stereo channel plus the feedback of the opposite channel's delay buffer should be be fed into each delay.
Here is a good image of the audio signal graph of it:
Here is some pseudo-code of the logic:
float wetDryMix = 0.5f;
float wetFactor = wetDryMix;
float dryFactor = 1.0f - wetDryMix;
float feedback = 0.6f;
int sampleRate = 44100;
int sampleCount = sampleRate * 10;
float[] leftInSamples = new float[sampleCount];
float[] rightInSamples = new float[sampleCount];
float[] leftOutSamples = new float[sampleCount];
float[] rightOutSamples = new float[sampleCount];
int delayBufferSize = sampleRate * 3;
float[] delayBufferLeft = new float[delayBufferSize];
float[] delayBufferRight = new float[delayBufferSize];
int delaySamples = sampleRate / 2;
int delayReadIndex = 0;
int delayWriteIndex = delaySamples;
for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) {
//Read samples in from input
leftChannel = leftInSamples[sampleIndex];
rightChannel = rightInSamples[sampleIndex];
//Make sure delay ring buffer indices are within range
delayReadIndex = delayReadIndex % delayBufferSize;
delayWriteIndex = delayWriteIndex % delayBufferSize;
//Get the current output of delay ring buffer
float delayOutLeft = delayBufferLeft[delayReadIndex];
float delayOutRight = delayBufferRight[delayReadIndex];
//Calculate what is put into delay buffer. It is the current input signal plus the delay output attenuated by the feedback factor
//Notice that the right delay output is fed into the left delay and vice versa
//In this version sound from each stereo channel will ping pong back and forth
float delayInputLeft = leftChannel + delayOutRight * feedback;
float delayInputRight = rightChannel + delayOutLeft * feedback;
//Alternatively you could use a mono signal that is pushed to one delay channel along with the current feedback delay
//This will ping-pong a mixed mono signal between channels
//float delayInputLeft = leftChannel + rightChannel + delayOutRight * feedback;
//float delayInputRight = delayOutLeft * feedback;
//Push the calculated delay value into the delay ring buffers
delayBufferLeft[delayWriteIndex] = delayInputLeft;
delayBufferRight[delayWriteIndex] = delayInputRight;
//Calculate resulting output by mixing the dry input signal with the current delayed output
float outputLeft = leftChannel * dryFactor + delayOutLeft * wetFactor;
float outputRight = rightChannel * dryFactor + delayOutRight * wetFactor;
leftOutSamples[sampleIndex] = outputLeft;
rightOutSamples[sampleIndex] = outputRight;
//Increment ring buffer indices
delayReadIndex++;
delayWriteIndex++;
}

Compilation error (Missing Library) under Arduino IDE

I have been trying to compile a code for a accelerometer which is avaiable from two sources but referring to the same code on github:
https://github.com/ayildirim/OpenVR
https://github.com/ptrbrtz/razor-9dof-ahrs/
Both of this sources contain the following arduino code(c++):
#define HW__VERSION_CODE 10736 // SparkFun "9DOF Razor IMU" version "SEN-10736" (HMC5883L magnetometer)
// OUTPUT OPTIONS
/*****************************************************************/
// Set your serial port baud rate used to send out data here!
#define OUTPUT__BAUD_RATE 57600
// Sensor data output interval in milliseconds
// This may not work, if faster than 20ms (=50Hz)
// Code is tuned for 20ms, so better leave it like that
#define OUTPUT__DATA_INTERVAL 20 // in milliseconds
// Output mode definitions (do not change)
#define OUTPUT__MODE_CALIBRATE_SENSORS 0 // Outputs sensor min/max values as text for manual calibration
#define OUTPUT__MODE_ANGLES 1 // Outputs yaw/pitch/roll in degrees
#define OUTPUT__MODE_SENSORS_CALIB 2 // Outputs calibrated sensor values for all 9 axes
#define OUTPUT__MODE_SENSORS_RAW 3 // Outputs raw (uncalibrated) sensor values for all 9 axes
#define OUTPUT__MODE_SENSORS_BOTH 4 // Outputs calibrated AND raw sensor values for all 9 axes
// Output format definitions (do not change)
#define OUTPUT__FORMAT_TEXT 0 // Outputs data as text
#define OUTPUT__FORMAT_BINARY 1 // Outputs data as binary float
// Select your startup output mode and format here!
int output_mode = OUTPUT__MODE_ANGLES;
int output_format = OUTPUT__FORMAT_TEXT;
// Select if serial continuous streaming output is enabled per default on startup.
#define OUTPUT__STARTUP_STREAM_ON true // true or false
// If set true, an error message will be output if we fail to read sensor data.
// Message format: "!ERR: reading <sensor>", followed by "\r\n".
boolean output_errors = false; // true or false
// Bluetooth
// You can set this to true, if you have a Rovering Networks Bluetooth Module attached.
// The connect/disconnect message prefix of the module has to be set to "#".
// (Refer to manual, it can be set like this: SO,#)
// When using this, streaming output will only be enabled as long as we're connected. That way
// receiver and sender are synchronzed easily just by connecting/disconnecting.
// It is not necessary to set this! It just makes life easier when writing code for
// the receiving side. The Processing test sketch also works without setting this.
// NOTE: When using this, OUTPUT__STARTUP_STREAM_ON has no effect!
#define OUTPUT__HAS_RN_BLUETOOTH false // true or false
// SENSOR CALIBRATION
/*****************************************************************/
// How to calibrate? Read the tutorial at http://dev.qu.tu-berlin.de/projects/sf-razor-9dof-ahrs
// Put MIN/MAX and OFFSET readings for your board here!
// Accelerometer
// "accel x,y,z (min/max) = X_MIN/X_MAX Y_MIN/Y_MAX Z_MIN/Z_MAX"
#define ACCEL_X_MIN ((float) -289)
#define ACCEL_X_MAX ((float) 294)
#define ACCEL_Y_MIN ((float) -268)
#define ACCEL_Y_MAX ((float) 288)
#define ACCEL_Z_MIN ((float) -294)
#define ACCEL_Z_MAX ((float) 269)
// Magnetometer (standard calibration)
// "magn x,y,z (min/max) = X_MIN/X_MAX Y_MIN/Y_MAX Z_MIN/Z_MAX"
//#define MAGN_X_MIN ((float) -600)
//#define MAGN_X_MAX ((float) 600)
//#define MAGN_Y_MIN ((float) -600)
//#define MAGN_Y_MAX ((float) 600)
//#define MAGN_Z_MIN ((float) -600)
//#define MAGN_Z_MAX ((float) 600)
// Magnetometer (extended calibration)
// Uncommend to use extended magnetometer calibration (compensates hard & soft iron errors)
#define CALIBRATION__MAGN_USE_EXTENDED true
const float magn_ellipsoid_center[3] = {
3.80526, -16.4455, 87.4052};
const float magn_ellipsoid_transform[3][3] = {
{
0.970991, 0.00583310, -0.00265756 }
, {
0.00583310, 0.952958, 2.76726e-05 }
, {
-0.00265756, 2.76726e-05, 0.999751 }
};
// Gyroscope
// "gyro x,y,z (current/average) = .../OFFSET_X .../OFFSET_Y .../OFFSET_Z
#define GYRO_AVERAGE_OFFSET_X ((float) 23.85)
#define GYRO_AVERAGE_OFFSET_Y ((float) -53.41)
#define GYRO_AVERAGE_OFFSET_Z ((float) -15.32)
/*
// Calibration example:
// "accel x,y,z (min/max) = -278.00/270.00 -254.00/284.00 -294.00/235.00"
#define ACCEL_X_MIN ((float) -278)
#define ACCEL_X_MAX ((float) 270)
#define ACCEL_Y_MIN ((float) -254)
#define ACCEL_Y_MAX ((float) 284)
#define ACCEL_Z_MIN ((float) -294)
#define ACCEL_Z_MAX ((float) 235)
// "magn x,y,z (min/max) = -511.00/581.00 -516.00/568.00 -489.00/486.00"
//#define MAGN_X_MIN ((float) -511)
//#define MAGN_X_MAX ((float) 581)
//#define MAGN_Y_MIN ((float) -516)
//#define MAGN_Y_MAX ((float) 568)
//#define MAGN_Z_MIN ((float) -489)
//#define MAGN_Z_MAX ((float) 486)
// Extended magn
#define CALIBRATION__MAGN_USE_EXTENDED true
const float magn_ellipsoid_center[3] = {91.5, -13.5, -48.1};
const float magn_ellipsoid_transform[3][3] = {{0.902, -0.00354, 0.000636}, {-0.00354, 0.9, -0.00599}, {0.000636, -0.00599, 1}};
// Extended magn (with Sennheiser HD 485 headphones)
//#define CALIBRATION__MAGN_USE_EXTENDED true
//const float magn_ellipsoid_center[3] = {72.3360, 23.0954, 53.6261};
//const float magn_ellipsoid_transform[3][3] = {{0.879685, 0.000540833, -0.0106054}, {0.000540833, 0.891086, -0.0130338}, {-0.0106054, -0.0130338, 0.997494}};
//"gyro x,y,z (current/average) = -32.00/-34.82 102.00/100.41 -16.00/-16.38"
#define GYRO_AVERAGE_OFFSET_X ((float) -34.82)
#define GYRO_AVERAGE_OFFSET_Y ((float) 100.41)
#define GYRO_AVERAGE_OFFSET_Z ((float) -16.38)
*/
// DEBUG OPTIONS
/*****************************************************************/
// When set to true, gyro drift correction will not be applied
#define DEBUG__NO_DRIFT_CORRECTION false
// Print elapsed time after each I/O loop
#define DEBUG__PRINT_LOOP_TIME false
/*****************************************************************/
/****************** END OF USER SETUP AREA! *********************/
/*****************************************************************/
// Check if hardware version code is defined
#ifndef HW__VERSION_CODE
// Generate compile error
#error YOU HAVE TO SELECT THE HARDWARE YOU ARE USING! See "HARDWARE OPTIONS" in "USER SETUP AREA" at top of Razor_AHRS.pde (or .ino)!
#endif
#include <Wire.h>
#include <Compass.h>
#include <DCM.h>
#include <Math.h>
#include <Output.h>
#include <Sensors.h>
// Sensor calibration scale and offset values
#define ACCEL_X_OFFSET ((ACCEL_X_MIN + ACCEL_X_MAX) / 2.0f)
#define ACCEL_Y_OFFSET ((ACCEL_Y_MIN + ACCEL_Y_MAX) / 2.0f)
#define ACCEL_Z_OFFSET ((ACCEL_Z_MIN + ACCEL_Z_MAX) / 2.0f)
#define ACCEL_X_SCALE (GRAVITY / (ACCEL_X_MAX - ACCEL_X_OFFSET))
#define ACCEL_Y_SCALE (GRAVITY / (ACCEL_Y_MAX - ACCEL_Y_OFFSET))
#define ACCEL_Z_SCALE (GRAVITY / (ACCEL_Z_MAX - ACCEL_Z_OFFSET))
#define MAGN_X_OFFSET ((MAGN_X_MIN + MAGN_X_MAX) / 2.0f)
#define MAGN_Y_OFFSET ((MAGN_Y_MIN + MAGN_Y_MAX) / 2.0f)
#define MAGN_Z_OFFSET ((MAGN_Z_MIN + MAGN_Z_MAX) / 2.0f)
#define MAGN_X_SCALE (100.0f / (MAGN_X_MAX - MAGN_X_OFFSET))
#define MAGN_Y_SCALE (100.0f / (MAGN_Y_MAX - MAGN_Y_OFFSET))
#define MAGN_Z_SCALE (100.0f / (MAGN_Z_MAX - MAGN_Z_OFFSET))
// Gain for gyroscope (ITG-3200)
#define GYRO_GAIN 0.06957 // Same gain on all axes
#define GYRO_SCALED_RAD(x) (x * TO_RAD(GYRO_GAIN)) // Calculate the scaled gyro readings in radians per second
// DCM parameters
#define Kp_ROLLPITCH 0.02f
#define Ki_ROLLPITCH 0.00002f
#define Kp_YAW 1.2f
#define Ki_YAW 0.00002f
// Stuff
#define STATUS_LED_PIN 13 // Pin number of status LED
#define GRAVITY 256.0f // "1G reference" used for DCM filter and accelerometer calibration
#define TO_RAD(x) (x * 0.01745329252) // *pi/180
#define TO_DEG(x) (x * 57.2957795131) // *180/pi
// Sensor variables
float accel[3]; // Actually stores the NEGATED acceleration (equals gravity, if board not moving).
float accel_min[3];
float accel_max[3];
float magnetom[3];
float magnetom_min[3];
float magnetom_max[3];
float magnetom_tmp[3];
float gyro[3];
float gyro_average[3];
int gyro_num_samples = 0;
// DCM variables
float MAG_Heading;
float Accel_Vector[3]= {
0, 0, 0}; // Store the acceleration in a vector
float Gyro_Vector[3]= {
0, 0, 0}; // Store the gyros turn rate in a vector
float Omega_Vector[3]= {
0, 0, 0}; // Corrected Gyro_Vector data
float Omega_P[3]= {
0, 0, 0}; // Omega Proportional correction
float Omega_I[3]= {
0, 0, 0}; // Omega Integrator
float Omega[3]= {
0, 0, 0};
float errorRollPitch[3] = {
0, 0, 0};
float errorYaw[3] = {
0, 0, 0};
float DCM_Matrix[3][3] = {
{
1, 0, 0 }
, {
0, 1, 0 }
, {
0, 0, 1 }
};
float Update_Matrix[3][3] = {
{
0, 1, 2 }
, {
3, 4, 5 }
, {
6, 7, 8 }
};
float Temporary_Matrix[3][3] = {
{
0, 0, 0 }
, {
0, 0, 0 }
, {
0, 0, 0 }
};
// Euler angles
float yaw;
float pitch;
float roll;
// DCM timing in the main loop
unsigned long timestamp;
unsigned long timestamp_old;
float G_Dt; // Integration time for DCM algorithm
// More output-state variables
boolean output_stream_on;
boolean output_single_on;
int curr_calibration_sensor = 0;
boolean reset_calibration_session_flag = true;
int num_accel_errors = 0;
int num_magn_errors = 0;
int num_gyro_errors = 0;
void read_sensors() {
Read_Gyro(); // Read gyroscope
Read_Accel(); // Read accelerometer
Read_Magn(); // Read magnetometer
}
// Read every sensor and record a time stamp
// Init DCM with unfiltered orientation
// TODO re-init global vars?
void reset_sensor_fusion() {
float temp1[3];
float temp2[3];
float xAxis[] = {
1.0f, 0.0f, 0.0f };
read_sensors();
timestamp = millis();
// GET PITCH
// Using y-z-plane-component/x-component of gravity vector
pitch = -atan2(accel[0], sqrt(accel[1] * accel[1] + accel[2] * accel[2]));
// GET ROLL
// Compensate pitch of gravity vector
Vector_Cross_Product(temp1, accel, xAxis);
Vector_Cross_Product(temp2, xAxis, temp1);
// Normally using x-z-plane-component/y-component of compensated gravity vector
// roll = atan2(temp2[1], sqrt(temp2[0] * temp2[0] + temp2[2] * temp2[2]));
// Since we compensated for pitch, x-z-plane-component equals z-component:
roll = atan2(temp2[1], temp2[2]);
// GET YAW
Compass_Heading();
yaw = MAG_Heading;
// Init rotation matrix
init_rotation_matrix(DCM_Matrix, yaw, pitch, roll);
}
// Apply calibration to raw sensor readings
void compensate_sensor_errors() {
// Compensate accelerometer error
accel[0] = (accel[0] - ACCEL_X_OFFSET) * ACCEL_X_SCALE;
accel[1] = (accel[1] - ACCEL_Y_OFFSET) * ACCEL_Y_SCALE;
accel[2] = (accel[2] - ACCEL_Z_OFFSET) * ACCEL_Z_SCALE;
// Compensate magnetometer error
#if CALIBRATION__MAGN_USE_EXTENDED == true
for (int i = 0; i < 3; i++)
magnetom_tmp[i] = magnetom[i] - magn_ellipsoid_center[i];
Matrix_Vector_Multiply(magn_ellipsoid_transform, magnetom_tmp, magnetom);
#else
magnetom[0] = (magnetom[0] - MAGN_X_OFFSET) * MAGN_X_SCALE;
magnetom[1] = (magnetom[1] - MAGN_Y_OFFSET) * MAGN_Y_SCALE;
magnetom[2] = (magnetom[2] - MAGN_Z_OFFSET) * MAGN_Z_SCALE;
#endif
// Compensate gyroscope error
gyro[0] -= GYRO_AVERAGE_OFFSET_X;
gyro[1] -= GYRO_AVERAGE_OFFSET_Y;
gyro[2] -= GYRO_AVERAGE_OFFSET_Z;
}
// Reset calibration session if reset_calibration_session_flag is set
void check_reset_calibration_session()
{
// Raw sensor values have to be read already, but no error compensation applied
// Reset this calibration session?
if (!reset_calibration_session_flag) return;
// Reset acc and mag calibration variables
for (int i = 0; i < 3; i++) {
accel_min[i] = accel_max[i] = accel[i];
magnetom_min[i] = magnetom_max[i] = magnetom[i];
}
// Reset gyro calibration variables
gyro_num_samples = 0; // Reset gyro calibration averaging
gyro_average[0] = gyro_average[1] = gyro_average[2] = 0.0f;
reset_calibration_session_flag = false;
}
void turn_output_stream_on()
{
output_stream_on = true;
digitalWrite(STATUS_LED_PIN, HIGH);
}
void turn_output_stream_off()
{
output_stream_on = false;
digitalWrite(STATUS_LED_PIN, LOW);
}
// Blocks until another byte is available on serial port
char readChar()
{
while (Serial.available() < 1) {
} // Block
return Serial.read();
}
void setup()
{
// Init serial output
Serial.begin(OUTPUT__BAUD_RATE);
// Init status LED
pinMode (STATUS_LED_PIN, OUTPUT);
digitalWrite(STATUS_LED_PIN, LOW);
// Init sensors
delay(50); // Give sensors enough time to start
I2C_Init();
Accel_Init();
Magn_Init();
Gyro_Init();
// Read sensors, init DCM algorithm
delay(20); // Give sensors enough time to collect data
reset_sensor_fusion();
// Init output
#if (OUTPUT__HAS_RN_BLUETOOTH == true) || (OUTPUT__STARTUP_STREAM_ON == false)
turn_output_stream_off();
#else
turn_output_stream_on();
#endif
}
// Main loop
void loop()
{
// Read incoming control messages
if (Serial.available() >= 2)
{
if (Serial.read() == '#') // Start of new control message
{
int command = Serial.read(); // Commands
if (command == 'f') // request one output _f_rame
output_single_on = true;
else if (command == 's') // _s_ynch request
{
// Read ID
byte id[2];
id[0] = readChar();
id[1] = readChar();
// Reply with synch message
Serial.print("#SYNCH");
Serial.write(id, 2);
Serial.println();
}
else if (command == 'o') // Set _o_utput mode
{
char output_param = readChar();
if (output_param == 'n') // Calibrate _n_ext sensor
{
curr_calibration_sensor = (curr_calibration_sensor + 1) % 3;
reset_calibration_session_flag = true;
}
else if (output_param == 't') // Output angles as _t_ext
{
output_mode = OUTPUT__MODE_ANGLES;
output_format = OUTPUT__FORMAT_TEXT;
}
else if (output_param == 'b') // Output angles in _b_inary format
{
output_mode = OUTPUT__MODE_ANGLES;
output_format = OUTPUT__FORMAT_BINARY;
}
else if (output_param == 'c') // Go to _c_alibration mode
{
output_mode = OUTPUT__MODE_CALIBRATE_SENSORS;
reset_calibration_session_flag = true;
}
else if (output_param == 's') // Output _s_ensor values
{
char values_param = readChar();
char format_param = readChar();
if (values_param == 'r') // Output _r_aw sensor values
output_mode = OUTPUT__MODE_SENSORS_RAW;
else if (values_param == 'c') // Output _c_alibrated sensor values
output_mode = OUTPUT__MODE_SENSORS_CALIB;
else if (values_param == 'b') // Output _b_oth sensor values (raw and calibrated)
output_mode = OUTPUT__MODE_SENSORS_BOTH;
if (format_param == 't') // Output values as _t_text
output_format = OUTPUT__FORMAT_TEXT;
else if (format_param == 'b') // Output values in _b_inary format
output_format = OUTPUT__FORMAT_BINARY;
}
else if (output_param == '0') // Disable continuous streaming output
{
turn_output_stream_off();
reset_calibration_session_flag = true;
}
else if (output_param == '1') // Enable continuous streaming output
{
reset_calibration_session_flag = true;
turn_output_stream_on();
}
else if (output_param == 'e') // _e_rror output settings
{
char error_param = readChar();
if (error_param == '0') output_errors = false;
else if (error_param == '1') output_errors = true;
else if (error_param == 'c') // get error count
{
Serial.print("#AMG-ERR:");
Serial.print(num_accel_errors);
Serial.print(",");
Serial.print(num_magn_errors);
Serial.print(",");
Serial.println(num_gyro_errors);
}
}
}
#if OUTPUT__HAS_RN_BLUETOOTH == true
// Read messages from bluetooth module
// For this to work, the connect/disconnect message prefix of the module has to be set to "#".
else if (command == 'C') // Bluetooth "#CONNECT" message (does the same as "#o1")
turn_output_stream_on();
else if (command == 'D') // Bluetooth "#DISCONNECT" message (does the same as "#o0")
turn_output_stream_off();
#endif // OUTPUT__HAS_RN_BLUETOOTH == true
}
else
{
} // Skip character
}
// Time to read the sensors again?
if((millis() - timestamp) >= OUTPUT__DATA_INTERVAL)
{
timestamp_old = timestamp;
timestamp = millis();
if (timestamp > timestamp_old)
G_Dt = (float) (timestamp - timestamp_old) / 1000.0f; // Real time of loop run. We use this on the DCM algorithm (gyro integration time)
else G_Dt = 0;
// Update sensor readings
read_sensors();
if (output_mode == OUTPUT__MODE_CALIBRATE_SENSORS) // We're in calibration mode
{
check_reset_calibration_session(); // Check if this session needs a reset
if (output_stream_on || output_single_on) output_calibration(curr_calibration_sensor);
}
else if (output_mode == OUTPUT__MODE_ANGLES) // Output angles
{
// Apply sensor calibration
compensate_sensor_errors();
// Run DCM algorithm
Compass_Heading(); // Calculate magnetic heading
Matrix_update();
Normalize();
Drift_correction();
Euler_angles();
if (output_stream_on || output_single_on) output_angles();
}
else // Output sensor values
{
if (output_stream_on || output_single_on) output_sensors();
}
output_single_on = false;
#if DEBUG__PRINT_LOOP_TIME == true
Serial.print("loop time (ms) = ");
Serial.println(millis() - timestamp);
#endif
}
#if DEBUG__PRINT_LOOP_TIME == true
else
{
Serial.println("waiting...");
}
#endif
}
And well, the code only includes the library which is for I2C communication, but there are 5 more files (.ino which is simply an .cpp) that have few functions being declared.
By just simply trying to compile the code, the following error is given:
Final_arduino_code.ino: In function ‘void read_sensors()’:
Final_arduino_code:427: error: ‘Read_Gyro’ was not declared in this scope
Final_arduino_code:428: error: ‘Read_Accel’ was not declared in this scope
Final_arduino_code:429: error: ‘Read_Magn’ was not declared in this scope
Final_arduino_code.ino: In function ‘void reset_sensor_fusion()’:
Final_arduino_code:450: error: ‘Vector_Cross_Product’ was not declared in this scope
Final_arduino_code:458: error: ‘Compass_Heading’ was not declared in this scope
Final_arduino_code:462: error: ‘init_rotation_matrix’ was not declared in this scope
Final_arduino_code.ino: In function ‘void compensate_sensor_errors()’:
Final_arduino_code:476: error: ‘Matrix_Vector_Multiply’ was not declared in this scope
Final_arduino_code.ino: In function ‘void setup()’:
Final_arduino_code:541: error: ‘I2C_Init’ was not declared in this scope
Final_arduino_code:542: error: ‘Accel_Init’ was not declared in this scope
Final_arduino_code:543: error: ‘Magn_Init’ was not declared in this scope
Final_arduino_code:544: error: ‘Gyro_Init’ was not declared in this scope
Final_arduino_code.ino: In function ‘void loop()’:
Final_arduino_code:675: error: ‘output_calibration’ was not declared in this scope
Final_arduino_code:683: error: ‘Compass_Heading’ was not declared in this scope
Final_arduino_code:684: error: ‘Matrix_update’ was not declared in this scope
Final_arduino_code:685: error: ‘Normalize’ was not declared in this scope
Final_arduino_code:686: error: ‘Drift_correction’ was not declared in this scope
Final_arduino_code:687: error: ‘Euler_angles’ was not declared in this scope
Final_arduino_code:689: error: ‘output_angles’ was not declared in this scope
Final_arduino_code:693: error: ‘output_sensors’ was not declared in this scope
Well, most of those functions have being declared in the other files in the same folder of the this main code, BUT, I have tried making a header (.h) to each of the files, just declaring the functions, it didn't work, I have tried including the files as they are, didn't work, tried to change them to .cpp and including, didn't work.
I posted as an issue to both of the github pages but still got no answer.
Please help me to fix these errors, thanks in advance.
but there are 5 more files (.ino which is simply an .cpp)
It is not that simple, they are not .cpp files. They are supposed to be built with the Ino toolkit, the project's home page is here. Judging from the compiler errors you get, you are not using this toolkit.
The core part that's missing are the .h files that the compiler normally needs to understand what functions like Read_Gyro() look like. Currently the projects you listed have no .h file and no corresponding #include directives. Not actually sure how Ino works but I'd guess it acts like a preprocessor that merges the .ino files into one big ball of source code before letting the compiler lose on it.
Using the toolkit is strongly recommended to get ahead and avoid substantial changes.
As I do not have enough reputation, I'll tell how the Guilherme Garcia da Rosa's answer put me on the right direction.
Unfortunately his contribution appears to be no longer valid with Arduino IDE 1.6.5
I managed to open the project this way :
1- Close Arduino IDE first
2- Create a directory named Final_arduino_code (maybe case sensitive)
3- Open Arduino IDE, and the sketch Final_arduino_code.ino
The IDE will automatically load all files.
The program uploaded successfully for me this way.
The original project owner "Ahmet YILDIRIM" replied to my problem and helped me to compile the project, this was his answer:
You know when you try opening an INO file, Arduino IDE asks you if you
would like to create a new folder for that specific file.
If you click yes, it seperates that file into a new folder.
If I remember correctly you should either press “No” then add other
files as new tabs. If you click “Yes”, then add other files into new
created folder and then open them all in new tabs.
I hope it helps

Distortion with chorus

I am new to plug in Development and C++. I was trying to write a chorus plug in using XCode Audio Unit Template. However, when I test the plug in with a sine wave I can hear some mild distortion. I believe I did something wrong with the interpolation technique I am using even though I went through it a thousand times and could not figure out what I did wrong. Here is the code I have written that includes the important parts of the audio unit:
private: //state variables...
enum {kWaveArraySize = 2000}; //number of points in the LFO sine array to hold the points
float mSine[kWaveArraySize];
float *waveArrayPointer; //pointer to point in the array Variable to hold Sampling Rate
Float32 SR;
long mSamplesProcessed; //variable to keep track of samples processed
enum {sampleLimit = (int)10E6}; //limit to reset sine wave
float mCurrentScale, mNextScale; //scaling factor for the LFO sine
TAUBuffer<Float32> Buffer; //circular buffer
Float32 rawIndex; //raw read Index
UInt32 ReadIndex, NextIndex; //the Read Index and the sample after the Read Index for Linear Interpolation
UInt32 WriteIndex; //the Write Index
UInt32 BufferSize; //Size of Buffer
UInt32 MaxBufferSize; //Allocated Number of Samples
Float32 DelayTime; //Delay Time going to be calculated according to LFO
Float32 inputSample, outputSample,
freq, Depth, //Variables to hold the frequency of the LFO and Depth parameter
samplesPerCycle, //number of samples per LFO cycle
InterpOutput, //interpolated output variable
fracDelay, DryValue, WetValue; //fractional Delay, Dry and Wet value variables
VibratoUnit::VibratoUnitKernel::VibratoUnitKernel (AUEffectBase *inAudioUnit) : AUKernelBase (inAudioUnit),
mSamplesProcessed(0), mCurrentScale(0)
{
for (int i = 0; i<kWaveArraySize; ++i) //loop to calculate one cycle of LFO
{
double radians = i * 2.0 * pi / kWaveArraySize;
mSine[i] = (sin(radians) + 1.0) * 0.5;
}
SR = GetSampleRate();
BufferSize = SR;
MaxBufferSize = BufferSize + 20;
Buffer.AllocateClear(MaxBufferSize);
ReadIndex = MaxBufferSize - 1;
WriteIndex = MaxBufferSize - 1; //Give both ReadIndex and WriteIndex a Value outside the buffer so they would be reset to 0 in the process method
void VibratoUnit::VibratoUnitKernel::Reset() //Reset and clear
{
mCurrentScale = 0;
mSamplesProcessed = 0;
Buffer.Clear();
}
//------------------PROCESS METHOD-----------------------//
void VibratoUnit::VibratoUnitKernel::Process( const Float32 *inSourceP,
Float32 *inDestP,
UInt32 inFramesToProcess,
UInt32 inNumChannels,
bool &ioSilence )
{
UInt32 nSampleFrames = inFramesToProcess;
const Float32 *sourceP = inSourceP;
Float32 *destP = inDestP;
freq = GetParameter(kParamFreq);
Depth = GetParameter(kParamDepth);
Depth = (SR/1000.0)*Depth;
WetValue = GetParameter(kParamDryWet);
DryValue = 1.0 - WetValue;
waveArrayPointer = &mSine[0];
samplesPerCycle = SR/freq;
mNextScale = kWaveArraySize/samplesPerCycle;
//----processing loop----//
while (nSampleFrames-- > 0) {
int index = static_cast<long> (mSamplesProcessed * mCurrentScale)%kWaveArraySize; //Find index for in the LFO wave table
if ((mNextScale != mCurrentScale) && (index == 0))
{
mCurrentScale = mNextScale;
mSamplesProcessed = 0; //change LFO in 0 crossing
}
if ((mSamplesProcessed >= sampleLimit) && (index == 0))
{
mSamplesProcessed = 0; // reset samples processed
}
if (WriteIndex >= BufferSize) //reset write Index if goes outside the buffer
{
WriteIndex = 0;
}
inputSample = *sourceP;
sourceP += inNumChannels;
DelayTime = waveArrayPointer[index]; //receive raw sine value between 0 and 1
DelayTime = (Depth*DelayTime)+Depth; //calculate delay value according to sine wave
rawIndex = WriteIndex - DelayTime; //calculate rawIndex relative to the write Index position
if (rawIndex < 0) {
rawIndex = BufferSize + rawIndex;
}
ReadIndex = (UInt32)rawIndex; //calculate readIndex according to rawIndex position
fracDelay = DelayTime - (UInt32)DelayTime; //calculate fractional delay time
NextIndex = ReadIndex + 1; //for interpolation
if (NextIndex >= BufferSize) //bounds checking
{
NextIndex = 0;
}
InterpOutput = (fracDelay*Buffer[ReadIndex]) + ((1.0-fracDelay)*Buffer[NextIndex]); //calculate interpolated value
Buffer[ReadIndex] = InterpOutput; //write the interpolated output to buffer
Buffer[WriteIndex] = inputSample; //write inputsample to buffer
outputSample = (Buffer[ReadIndex]*WetValue) + (inputSample * DryValue); //read output sample from buffer
WriteIndex++; //increment writeIndex
mSamplesProcessed++; //increment samplesprocessed
*destP = outputSample;
destP += inNumChannels;
}
}
Thank you for your help in advance.

For an Arduino Sketch based light meter, functions outside of 'loop' are not being set off/firing

I'm very new to Arduino. I have much more experience with Java and ActionScript 3. I'm working on building a light meter out of an Arduino Uno and a TAOS TSL235R light-to-frequency converter.
I can only find a tuturial using a different sensor, so I am working my way through converting what I need to get it all to work (AKA some copy and paste, shamefully, but I'm new to this).
There are three parts: this is the first tutorial of the series Arduino and the Taos TSL230R Light Sensor: Getting Started.
The photographic conversion: Arduino and the TSL230R: Photographic Conversions.
At first, I could return values for the frequency created by the TSL235R sensor, but once I tried to add the code for photographic conversions I only get zero returned, and none of the funcions outside of the main loop seem to fire being that my Serial.Println() doesn't return anything.
I am more concerned with making the functions fire than if my math is perfect. In ActionScript and Java there are event listeners for functions and such, do I need to declare the function for it to fire in C/C++?
Basically, how can I make sure all my functions fire in the C programming language?
My Arduino Sketch:
// TSL230R Pin Definitions
#define TSL_FREQ_PIN 2
// Our pulse counter for our interrupt
unsigned long pulse_cnt = 0;
// How often to calculate frequency
// 1000 ms = 1 second
#define READ_TM 1000
// Two variables used to track time
unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;
// We'll need to access the amount of time passed
unsigned int tm_diff = 0;
unsigned long frequency;
unsigned long freq;
float lux;
float Bv;
float Sv;
// Set our frequency multiplier to a default of 1
// which maps to output frequency scaling of 100x.
int freq_mult = 100;
// We need to measure what to divide the frequency by:
// 1x sensitivity = 10,
// 10x sensitivity = 100,
// 100x sensitivity = 1000
int calc_sensitivity = 10;
void setup() {
attachInterrupt(0, add_pulse, RISING); // Attach interrupt to pin2.
pinMode(TSL_FREQ_PIN, INPUT); //Send output pin to Arduino
Serial.begin(9600); //Start the serial connection with the copmuter.
}//setup
void loop(){
// Check the value of the light sensor every READ_TM ms and
// calculate how much time has passed.
pre_tm = cur_tm;
cur_tm = millis();
if( cur_tm > pre_tm ) {
tm_diff += cur_tm - pre_tm;
}
else
if( cur_tm < pre_tm ) {
// Handle overflow and rollover (Arduino 011)
tm_diff += ( cur_tm + ( 34359737 - pre_tm ));
}
// If enough time has passed to do a new reading...
if (tm_diff >= READ_TM ) {
// Reset the ms counter
tm_diff = 0;
// Get our current frequency reading
frequency = get_tsl_freq();
// Calculate radiant energy
float uw_cm2 = calc_uwatt_cm2( frequency );
// Calculate illuminance
float lux = calc_lux_single( uw_cm2, 0.175 );
}
Serial.println(freq);
delay(1000);
} //Loop
unsigned long get_tsl_freq() {
// We have to scale out the frequency --
// Scaling on the TSL230R requires us to multiply by a factor
// to get actual frequency.
unsigned long freq = pulse_cnt * 100;
// Reset pulse counter
pulse_cnt = 0;
return(freq);
Serial.println("freq");
} //get_tsl_freq
void add_pulse() {
// Increase pulse count
pulse_cnt++;
return;
Serial.println("Pulse");
}//pulse
float calc_lux_single(float uw_cm2, float efficiency) {
// Calculate lux (lm/m^2), using standard formula
// Xv = Xl * V(l) * Km
// where Xl is W/m^2 (calculate actual received uW/cm^2, extrapolate from sensor size
// to whole cm size, then convert uW to W),
// V(l) = efficiency function (provided via argument) and
// Km = constant, lm/W # 555 nm = 683 (555 nm has efficiency function of nearly 1.0).
//
// Only a single wavelength is calculated - you'd better make sure that your
// source is of a single wavelength... Otherwise, you should be using
// calc_lux_gauss() for multiple wavelengths.
// Convert to w_m2
float w_m2 = (uw_cm2 / (float) 1000000) * (float) 100;
// Calculate lux
float lux = w_m2 * efficiency * (float) 683;
return(lux);
Serial.println("Get lux");
} //lux_single
float calc_uwatt_cm2(unsigned long freq) {
// Get uW observed - assume 640 nm wavelength.
// Note the divide-by factor of ten -
// maps to a sensitivity of 1x.
float uw_cm2 = (float) freq / (float) 10;
// Extrapolate into the entire cm2 area
uw_cm2 *= ( (float) 1 / (float) 0.0136 );
return(uw_cm2);
Serial.println("Get uw_cm2");
} //calc_uwatt
float calc_ev( float lux, int iso ) {
// Calculate EV using the APEX method:
//
// Ev = Av + Tv = Bv + Sv
//
// We'll use the right-hand side for this operation:
//
// Bv = log2( B/NK )
// Sv = log2( NSx )
float Sv = log( (float) 0.3 * (float) iso ) / log(2);
float Bv = log( lux / ( (float) 0.3 * (float) 14 ) ) / log(2);
return( Bv + Sv );
Serial.println("get Bv+Sv");
}
float calc_exp_tm ( float ev, float aperture ) {
// Ev = Av + Tv = Bv + Sv
// need to determine Tv value, so Ev - Av = Tv
// Av = log2(Aperture^2)
// Tv = log2( 1/T ) = log2(T) = 2^(Ev - Av)
float exp_tm = ev - ( log( pow(aperture, 2) ) / log(2) );
float exp_log = pow(2, exp_tm);
return( exp_log );
Serial.println("get exp_log");
}
unsigned int calc_exp_ms( float exp_tm ) {
unsigned int cur_exp_tm = 0;
// Calculate mS of exposure, given a divisor exposure time.
if (exp_tm >= 2 ) {
// Deal with times less than or equal to half a second
if (exp_tm >= (float) int(exp_tm) + (float) 0.5 ) {
// Round up
exp_tm = int(exp_tm) + 1;
}
else {
// Round down
exp_tm = int(exp_tm);
}
cur_exp_tm = 1000 / exp_tm;
}
else if( exp_tm >= 1 ) {
// Deal with times larger than 1/2 second
float disp_v = 1 / exp_tm;
// Get first significant digit
disp_v = int( disp_v * 10 );
cur_exp_tm = ( 1000 * disp_v ) / 10;
}
else {
// Times larger than 1 second
int disp_v = int( (float) 1 / exp_tm);
cur_exp_tm = 1000 * disp_v;
}
return(cur_exp_tm);
Serial.println("get cur_exp_tm");
}
float calc_exp_aperture( float ev, float exp_tm ) {
float exp_apt = ev - ( log( (float) 1 / exp_tm ) / log(2) );
float apt_log = pow(2, exp_apt);
return( apt_log );
Serial.println("get apt_log");
}
That is a lot of code to read, where should I start.
In your loop() you are assigning frequency but printing freq
// get our current frequency reading
frequency = get_tsl_freq();
-- snip --
Serial.println(freq);
in get_tsl_freq() you are creating a local unsigned int freq that hides the global freq and using that for calculation and returning the value, maybe that is also a source of confusion for you. I do not see a reason for frequency and freq to be globals in this code. The function also contains unreachable code, the control will leave the function on return, statements after the return will never be executed.
unsigned long get_tsl_freq() {
unsigned long freq = pulse_cnt * 100; <-- hides global variable freq
// re-set pulse counter
pulse_cnt = 0;
return(freq); <-- ( ) not needed
Serial.println("freq"); <-- Unreachable
}
Reading a bit more I can suggest you pick up a C++ book and read a bit. While your code compiles it is not technically valid C++, you get away with it thanks to the Arduino software that does some mangling and what not to allow using functions before they are declared.
On constants you use in your calculations
float w_m2 = (uw_cm2 / (float) 1000000) * (float) 100;
could be written as
float w_m2 = (uw_cm2 / 1000000.0f) * 100.0f;
or even like this because uw_cm2 is a float
float w_m2 = (uw_cm2 / 1000000) * 100;
You also seem to take both approaches to waiting, you have code that calculates and only runs if it has been more than 1000 msec since it was last run, but then you also delay(1000) in the same code, this may not work as expected at all.