Как изменить функцию БПФ 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

, 👍1


1 ответ


2

Библиотека Adafruit ZeroFFT не является полной заменой Библиотеки FFT.

Вы не можете легко использовать один и тот же код для обоих.

,