Как изменить функцию БПФ Arduino Uno для Arduino Zero?
#define LIN_OUT 1 // Include the resources for the linear output function
#define Adafruit_ZeroFFT 256 // Sets the ZeroFFT length to 256 points
#define MERR 10 // Number of error values to store in elist[MERR]
#define PID_ON 1 // Use PID feedback or not
#define TRI_PERIOD 100 // Half-period of triangle wave in loops
#define F_BLACKMAN 0.02463994238109641755656975202572 // Osillation freq. for Blackman filter
#define ARM_MATH_CM0PLUS
#include <arm_common_tables.h>
#include <arm_math.h>
#include <Adafruit_ZeroFFT.h>
#include <SPI.h>
// Photodiode array variables
byte CLKpin = 4; // Arduino pin delivering the clock pulses to pin 3 (CLK) of the TSL1402R
byte SIpin = 5; // Arduino pin delivering the SI (serial-input) pulse to pin 2 of the TSL1402R
byte AOpin0 = A1; // Arduino pin connected to pin 4 (analog output 1)of the TSL1402R
byte AOpin1 = A2; // Arduino pin connected to pin 8 (analog output 2)of the TSL1402R
// Variables for determining the displacment from the ZeroFFT
int maxindex; // Index of the maximum of the ZeroFFT
float maxvalue; // For comparing the values of the ZeroFFT to find the global maximum
double kmax; // Spatial wavenumber corresponding to the dominant fringe modulation Fourier component
float Am; // Real part of Fourier coefficent corresponding to kmax
float Bm; // Imag part of Fourier coefficent corresponding to kmax
float theta; // Phase angle of Fourier transform at kmax
float preTheta = 0; // Storage for previous value of phase angle
int Nwrap = 0; // Number of phase wraps
float displacement; // Displacement in nanometers
float predisplacement; // Storage for initial value of displacement
int w = 0;
int prevw = 0;
int wdiff = 0;
// PID Variables
unsigned long lastTime;
double Output=0; // Output value for PID (voltage to the piezoelectric actuator (in millivolts))
double Setpoint; // Desired value of displacement (in nm)
double kp = 0 / 1; // 0 proportional gain for PID
double ki = 2/1; // (1000 / (138.5)) integral gain for PID
//double ki = 2/ 1; // (1000 / (138.5)) integral gain for PID
double kd = 0/ 100; // 0 derivative gain for PID
double error; // Error signal; difference between setpoint and displacement (in nm)
double preverror; // Stores previous value of error for derivative control
float esum; // Integral of error signal over time
float D; // Derivative of error signal
unsigned long time0 = 0; // Used in calculating the derivative term
float MSerror = 0; // Mean squared error
float RMSerror = 0; // Root mean squared error
float elist[MERR];// Array of last MERR error values
int jerr = 0; // index of integral error term
float runningRMSerror = 0; // RMS error calc'd from elist
float m = 0; // extra variables for one time calculations
float pchange = 0;
float lastp = 0;
float k = 1;
int p = 1;
float M = 0;
//int switchtime = 1200; // Time (in ms) between Setpoint switches
void setup() {
Serial.begin(9600); // Initialize serial interface to computer (i.e. serial monitor or plotter)
INIT_PHOTO(); // Initialize the photodiode array
READ_PHOTO(); // Read the photodiode array
DO_ZeroFFT(); // Calculate the ZeroFFT of the photodiode array data
FIND_PEAK_INDEX(); // Determine index of peak in ZeroFFT
KMAX(); // Calculate spatial wavevector of the interferogram
INIT_PHOTO(); // Maybe could be replaced by START_EXPOSURE()
READ_PHOTO(); // Read photodiode again in preparation for next step
PHASE_ANGLE(); // Calculate the complex phase angle of the ZeroFFT peak
DISPLACEMENT(); // Calculate the displacement from the phase angle
predisplacement = displacement; // Save the initial displacement corresponding to center of PZT range
Setpoint = 0; // Define the initial setpoint
delay(100); // Allow things to settle before beginning loop
START_EXPOSURE(); // Turn on the photodiode array and begin integrating
}
void loop() {
KMAX(); // Calculate kmax from previous cycle's ZeroFFT
READ_PHOTO(); // Read photodiode array
PHASE_ANGLE(); // Calculate complex phase angle corresponding to kmax peak
WRAPPING(); // Determine if a phase wrap occurred
DISPLACEMENT(); // Calculate the displacement from the unwrapped phase
DO_ZeroFFT(); // Calculate the ZeroFFT of the photodiode array data
FIND_PEAK_INDEX(); // Determine index of peak in ZeroFFT
//OSC_SET(); // Oscillate the setpoint up and down
PID_LOOP(); // Perform feedback to follow the setpoint (if PID_ON is set to 1)
//OSC_DAC(); // Send an oscillating voltage to the DAC
//TRI_DAC(); // Send a triangular wave voltage to the DAC
START_EXPOSURE(); // Turn on the photodiode array and begin integrating for next cycle
SERIAL_PRINT(); // Print some outputs to the serial USB port
}
// Photodiode functions
void ClockPulse() { // For sending clock pulses during reading of photodiode
delayMicroseconds(1);
digitalWrite(CLKpin, HIGH);
digitalWrite(CLKpin, LOW);
}
void INIT_PHOTO() { // Intialization of photodiode
// Initialize two Arduino pins as digital output:
pinMode(CLKpin, OUTPUT);
pinMode(SIpin, OUTPUT);
// To set up the ADC, first remove bits set by Arduino library, then choose
for ( int i = 0; i < 14; i++ )
{
digitalWrite(i, LOW);
}
// Clock out any existing SI pulse through the ccd register:
for (int i = 0; i < 260; i++)
{
ClockPulse();
}
// Create a new SI pulse and clock out that same SI pulse through the sensor register:
digitalWrite(SIpin, HIGH);
ClockPulse();
digitalWrite(SIpin, LOW);
for (int i = 0; i < 260; i++)
{
ClockPulse();
}
}
void READ_PHOTO() { // Read the photodiode
// Stop the ongoing integration of light quanta from each photodiode by clocking in a SI pulse
// into the sensors register:
digitalWrite(SIpin, HIGH);
ClockPulse();
digitalWrite(SIpin, LOW);
// Next, read all 256 pixels in parallel. Store the result in the array. Each clock pulse
// causes a new pixel to expose its value on the two outputs:
for (int i = 0; i < 128; i++)
{
delayMicroseconds(20); // We add a delay to stabilize the AO output from the sensor
ZeroFFT_input[2 * i] = analogRead(AOpin0); // Output of first half of photodiode array
ZeroFFT_input[2 * i + 1] = 0; // Store zero in the "imaginary" part of the array
ZeroFFT_input[2 * i + 256] = analogRead(AOpin1); // Output of second half of photodiode array
ZeroFFT_input[2 * i + 257] = 0; // Store zero in the "imaginary" part of the array
ClockPulse();
}
// Next, AGAIN stop the ongoing integration of light quanta from each photodiode
// by clocking in a SI pulse. This is necessary because during the readout operation,
// the 18th clock pulse starts the integration of light intensity again.
// This way we can turn on the integration when we want using the START_EXPOSURE() command.
digitalWrite(SIpin, HIGH);
ClockPulse();
digitalWrite(SIpin, LOW);
// The photodiode remains OFF after this function completes.
// Call START_EXPOSURE() to turn on the photodiode array and begin integrating.
}
void START_EXPOSURE() {
// The photodiode array starts integrating once 18 clock pulses have passed.
// At that time, the photodiodes are once again active. We clock out the SI pulse through
// the 256 bit register in order to be ready to halt the ongoing measurement at our will
// (by clocking in a new SI pulse):
// To be used after all calculations are finished, but
// before the next photodiode read operation.
for (int i = 0; i < 260; i++)
{
if (i == 18)
{
// Now the photodiodes goes active..
// An external trigger can be placed here
}
ClockPulse();
}
// Uncomment the next line to increase the integration time.
//delay(15);// <-- Add 15 ms integration time
}
//Calculation Functions
void DO_ZeroFFT() { // Performs the ZeroFFT
ZeroFFT_reorder(); // Reorders the ZeroFFT_input array to allow the ZeroFFT_run() command to be used
ZeroFFT_run(); // This is the function that actually does the ZeroFFT
ZeroFFT_mag_lin(); // Produces a variable ZeroFFT_lin_out that contains the absolute values of the ZeroFFT, 128 elements long.
}
void FIND_PEAK_INDEX() { // Finds the index of the major peak in the ZeroFFT
maxvalue = 0;
maxindex = 0;
for (int i = 5; i < 128; i++) // Go through each element of the ZeroFFT (skip the DC peak)
{
if (ZeroFFT_lin_out[i] > maxvalue)
// If the magnitude is larger than the previously seen maximum...
{
maxvalue = ZeroFFT_lin_out[i]; // ...store the new max...
maxindex = i; // ...and the index at which it occurs.
}
}
}
void KMAX() {
// Calculates the spatial wavevector of the interferogram corresponding
// to the peak in the ZeroFFT.
kmax = 2 * PI / 256 * maxindex;
}
void PHASE_ANGLE() { // Calculates the complex phase angle of the ZeroFFT peak
// NOTE: This function must be called BEFORE the ZeroFFT is calculated.
Am = 0;
Bm = 0;
for (int i = 0; i < 256; i++) // Calculate the real and imag Fourier components
{
Am = Am + float ((ZeroFFT_input[2 * i]) * cos(kmax * i)); //magnitude of real part
Bm = Bm + float ((ZeroFFT_input[2 * i]) * sin(kmax * i)); //magnitude of imaginary part
}
theta = atan2(Bm, Am); // Complext phase angle (in radians)
}
void WRAPPING() { // Determines if a phase wrap/unwrap occured and accounts for it
if ((preTheta ) > (0.5 * PI) && (theta) < (-0.7 * PI)) {
// Compare the previous theat to the current theta to see if a wrap occured.
Nwrap = Nwrap + 1; // If so, add 1 to the number of wraps.
}
if ((preTheta) < (-0.7 * PI) && (theta) > (0.5 * PI)) {
// If an unwrap occured (a phase wrap in the other direction)...
Nwrap = Nwrap - 1; // ...then subtract 1 from the number of wraps.
}
preTheta = theta; // Store the current theta for the next cycle
}
void DISPLACEMENT() { // Calculate the displacement after the phase angle is determined
m = 2 * PI * Nwrap;
//M = theta + m;
displacement = ((-(theta + m) * 632) * (1 / (4 * PI)) * (1 / sqrt(2))) - predisplacement;
//displacement = ((-(theta + m) * 632) * (1 / (4 * PI)) * (0.80)) - predisplacement;
}
// Servo Functions
void PID_LOOP() { // Performs feedback signal for PID control
error = Setpoint - displacement;
// Store the current error signal; overwrite if necessary
if( jerr >= MERR ){
jerr = 0;
}
elist[jerr] = error;
jerr++;
// Calculate the running RMS error
runningRMSerror = 0;
for(int i=0; i<MERR; i++) {
runningRMSerror += pow(elist[i],2);
}
runningRMSerror = sqrt(runningRMSerror/MERR);
// Calculate the mean-squared and root-mean-square errors over all time
MSerror = (k - 1) / k * MSerror + pow(error, 2) / k;
RMSerror = sqrt(MSerror);
k = k + 1;
// Integral of error over all time
esum = esum + error;
// Derivative of error
time0 = millis();
D = (error - preverror) / (time0 - lastTime);
// The feedback signal (in millivolts)
// The minus signs are to make sure the piezo moves in the right direction
Output = -(kp * error) -(ki * esum) -(kd * D);
// Send the feedback to the DAC if PID_ON is 1
/*if (PID_ON) {
val = offset + Output;
val = max(val, 0); // Constrain the output voltage so that is stays in range
val = min(val, 4096);
DAC_TRANSFER();
}
// Save the current time and error for calc'ing the derivative next cycle
lastTime = time0;
preverror = error;*/
}
void SERIAL_PRINT(){
Serial.print(displacement);
Serial.print(" , ");
Serial.println(millis());
Serial.print(" ") ;
}
Привет всем. Я попытался скомпилировать этот код для Arduino Zero, который изначально был написан для Arduino Uno. Я получил следующие ошибки. Что я делаю не так?
Ошибка:
/Users/RAJU/Documents/Documents/All Folders/Arduino 2017_v03_Maintable/Arduino-zero/DIS_SET_V04_Arduino-zero/DIS_SET_V04_Arduino-zero.ino: In function 'void READ_PHOTO()':
DIS_SET_V04_Arduino-zero:144: error: 'ZeroFFT_input' was not declared in this scope
ZeroFFT_input[2 * i] = analogRead(AOpin0); // Output of first half of photodiode array
^
/Users/RAJU/Documents/Documents/All Folders/Arduino 2017_v03_Maintable/Arduino-zero/DIS_SET_V04_Arduino-zero/DIS_SET_V04_Arduino-zero.ino: In function 'void DO_ZeroFFT()':
DIS_SET_V04_Arduino-zero:186: error: 'ZeroFFT_reorder' was not declared in this scope
ZeroFFT_reorder(); // Reorders the ZeroFFT_input array to allow the ZeroFFT_run() command to be used
^
DIS_SET_V04_Arduino-zero:187: error: 'ZeroFFT_run' was not declared in this scope
ZeroFFT_run(); // This is the function that actually does the ZeroFFT
^
DIS_SET_V04_Arduino-zero:188: error: 'ZeroFFT_mag_lin' was not declared in this scope
ZeroFFT_mag_lin(); // Produces a variable ZeroFFT_lin_out that contains the absolute values of the ZeroFFT, 128 elements long.
^
/Users/RAJU/Documents/Documents/All Folders/Arduino 2017_v03_Maintable/Arduino-zero/DIS_SET_V04_Arduino-zero/DIS_SET_V04_Arduino-zero.ino: In function 'void FIND_PEAK_INDEX()':
DIS_SET_V04_Arduino-zero:196: error: 'ZeroFFT_lin_out' was not declared in this scope
if (ZeroFFT_lin_out[i] > maxvalue)
^
/Users/RAJU/Documents/Documents/All Folders/Arduino 2017_v03_Maintable/Arduino-zero/DIS_SET_V04_Arduino-zero/DIS_SET_V04_Arduino-zero.ino: In function 'void PHASE_ANGLE()':
DIS_SET_V04_Arduino-zero:217: error: 'ZeroFFT_input' was not declared in this scope
Am = Am + float ((ZeroFFT_input[2 * i]) * cos(kmax * i)); //magnitude of real part
^
exit status 1
'ZeroFFT_input' was not declared in this scope
/Users/RAJU/Documents/Arduino/libraries/Adafruit_Zero_FFT_Library/examples/mic_tft/mic_tft.ino
/Users/RAJU/Documents/Arduino/libraries/Adafruit_Zero_FFT_Library/examples/normalized/normalized.ino
@Raju KC, 👍1
1 ответ
▲ 2
Библиотека Adafruit ZeroFFT не является полной заменой Библиотеки FFT.
Вы не можете легко использовать один и тот же код для обоих.
,
@Craig
Смотрите также:
- Arduino zero Error: не удается найти устройство CMSIS-DAP
- Правильная схема карты Micro SD
- Высокочастотный PWM на Adafruit Feather M0
- Проблема Arduino MKR Zero с новой связью UART
- Arduino Zero - управление шаговым двигателем (прерывание)?
- Arduino Zero (ATSAMD21G) - I2C - непрерывный поток неверных данных
- Конфигурация Arduino Zero для Arduino Zero SPI
- Audio Zero не отвечает на MKR Zero