Как изменить функцию БПФ 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
У вас есть какие-либо предложения?, @Raju KC
Привет, Крейг, есть ли у тебя какие-либо идеи о том, как работает библиотека FFT в Arduino Zero?, @Raju KC
Нет, я никогда им не пользовался. Предлагаю прочитать исходный код и примеры., @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
Вы уверены, что это действительно скомпилировано для Arduino Uno? Используемая библиотека уже для Arduino Zero, которая полностью отличается от Uno. Откуда вы взяли этот код? Массив
ZeroFFT_input
должен быть где-то определен, в этом ошибка., @chrislЭто правда. Извините за путаницу. Этот код компилируется для Arduino Uno, если я заменю все Zero_FFT на FFT. Очевидно, мне придется закомментировать следующие строки синтаксиса, чтобы он заработал для Arduino Zero: #define Adafruit_ZeroFFT 256 #определить ARM_MATH_CM0PLUS #include <arm_common_tables.h> #include <arm_math.h> #include <Adafruit_ZeroFFT.h> И мне нужно добавить еще одну библиотеку <FFT.h>, чтобы она работала для Arduino Uno. Если хотите, я выложу код, который работает для Arduino Uno., @Raju KC