mirror of
https://github.com/nqrduck/ATM.git
synced 2024-11-23 10:32:27 +00:00
300 lines
10 KiB
C++
300 lines
10 KiB
C++
#include "ADF4351.h"
|
|
#include <TMC2130Stepper.h>
|
|
#include <AccelStepper.h>
|
|
#include <MultiStepper.h>
|
|
|
|
|
|
//SPI Pins
|
|
#define SCLK_PIN 14
|
|
#define MOSI_PIN 13
|
|
#define MISO_PIN 12
|
|
|
|
//ADF Pins
|
|
#define LE_PIN 27
|
|
#define CE_PIN 25
|
|
|
|
// Pins M1
|
|
#define EN_PIN_M1 25
|
|
#define DIR_PIN_M1 33
|
|
#define STEP_PIN_M1 32
|
|
#define CS_PIN_M1 26
|
|
|
|
#define DIAG1_PIN_M1 2 // used for homing
|
|
|
|
// Pins M2
|
|
#define EN_PIN_M2 17
|
|
#define DIR_PIN_M2 19
|
|
#define STEP_PIN_M2 5
|
|
#define CS_PIN_M2 18
|
|
|
|
#define DIAG1_PIN_M2 0 // used for homing
|
|
|
|
// Stall Detection sensitivity
|
|
#define STALL_VALUE -64 // [-64..63]
|
|
|
|
//ADC Pin
|
|
#define REFLECTION_PIN 15
|
|
|
|
// Frequency Settings
|
|
#define FREQUENCY_STEP 100000U // 100kHz frequency steps for initial frequency sweep
|
|
#define START_FREQUENCY 80000000U // 80MHz
|
|
#define STOP_FREQUENCY 160000000 // 120MHz
|
|
|
|
// Stepper Settings
|
|
#define STEPS_PER_ROTATION 3200U // 200 * 16 -> Microstepping
|
|
|
|
ADF4351 adf4351(SCLK_PIN, MOSI_PIN, LE_PIN, CE_PIN); // declares object PLL of type ADF4351
|
|
|
|
TMC2130Stepper tuning_driver = TMC2130Stepper(EN_PIN_M1, DIR_PIN_M1, STEP_PIN_M1, CS_PIN_M1, MOSI_PIN, MISO_PIN, SCLK_PIN);
|
|
TMC2130Stepper matching_driver = TMC2130Stepper(EN_PIN_M2, DIR_PIN_M2, STEP_PIN_M2, CS_PIN_M2, MOSI_PIN, MISO_PIN, SCLK_PIN);
|
|
|
|
AccelStepper tuning_stepper = AccelStepper(tuning_stepper.DRIVER, STEP_PIN_M1, DIR_PIN_M1);
|
|
AccelStepper matching_stepper = AccelStepper(matching_stepper.DRIVER, STEP_PIN_M2, DIR_PIN_M2);
|
|
|
|
void IRAM_ATTR tuningStall() {
|
|
Serial.println("Stall");
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
|
|
pinMode(MISO_PIN, INPUT_PULLUP); // Seems to be necessary for SPI to work
|
|
|
|
tuning_driver.begin(); // Initiate pins and registeries
|
|
tuning_driver.rms_current(400); // Set stepper current to 800mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
|
|
tuning_driver.microsteps(16);
|
|
tuning_driver.coolstep_min_speed(0xFFFFF); // 20bit max - needs to be set for stallguard
|
|
tuning_driver.diag1_stall(1);
|
|
tuning_driver.diag1_active_high(1);
|
|
tuning_driver.sg_stall_value(STALL_VALUE);
|
|
tuning_driver.shaft_dir(0);
|
|
|
|
pinMode(DIAG1_PIN_M1, INPUT);
|
|
attachInterrupt(DIAG1_PIN_M1, tuningStall, RISING);
|
|
|
|
Serial.print("DRV_STATUS=0b");
|
|
Serial.println(tuning_driver.DRV_STATUS(), BIN);
|
|
|
|
matching_driver.begin(); // Initiate pins and registeries
|
|
matching_driver.rms_current(600); // Set stepper current to 800mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
|
|
matching_driver.microsteps(16);
|
|
|
|
digitalWrite(EN_PIN_M1, LOW);
|
|
|
|
digitalWrite(EN_PIN_M2, LOW);
|
|
|
|
tuning_stepper.setMaxSpeed(12000);
|
|
tuning_stepper.setAcceleration(12000);
|
|
tuning_stepper.setEnablePin(EN_PIN_M1);
|
|
tuning_stepper.setPinsInverted(false, false, true);
|
|
tuning_stepper.enableOutputs();
|
|
|
|
matching_stepper.setMaxSpeed(12000);
|
|
matching_stepper.setAcceleration(12000);
|
|
matching_stepper.setEnablePin(EN_PIN_M2);
|
|
matching_stepper.setPinsInverted(false, false, true);
|
|
matching_stepper.enableOutputs();
|
|
|
|
tuning_stepper.setCurrentPosition(0);
|
|
|
|
matching_stepper.setCurrentPosition(0);
|
|
|
|
adf4351.begin();
|
|
|
|
adf4351.setrf(25000000U);
|
|
adf4351.pwrlevel = 0; // This equals -4dBm*/
|
|
|
|
///////////////////// TESTING ////////////////////////////
|
|
unsigned long stime = millis();
|
|
|
|
uint32_t target_frequency = 100000000U;
|
|
Serial.println("_______________________________________________");
|
|
Serial.println("Start - Target frequency is:");
|
|
Serial.println(target_frequency);
|
|
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
|
Serial.println("Resonance is at:");
|
|
Serial.println(resonance_frequency);
|
|
|
|
resonance_frequency = approximateResonance(target_frequency, resonance_frequency);
|
|
Serial.println("Resonance after approximation is at:");
|
|
Serial.println(resonance_frequency);
|
|
|
|
resonance_frequency = bruteforceResonance(target_frequency, resonance_frequency);
|
|
Serial.println("Resonance after bruteforce is at:");
|
|
Serial.println(resonance_frequency);
|
|
|
|
/*int reflection = optimizeMatching(resonance_frequency);
|
|
Serial.println("Minimum Reflection is:");
|
|
Serial.println(reflection);
|
|
|
|
resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
|
resonance_frequency = bruteforceResonance(target_frequency, resonance_frequency);
|
|
Serial.println("Resonance after bruteforce is at:");
|
|
Serial.println(resonance_frequency);*/
|
|
|
|
Serial.println("Matched in s");
|
|
Serial.println((millis()-stime)/ 1000);
|
|
|
|
|
|
|
|
}
|
|
|
|
void loop() {
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void homeStepper(){
|
|
|
|
}
|
|
|
|
// Finds current Resonance Frequency of the coil. There should be a substential dip already present atm.
|
|
// Add plausibility check to make sure there is one peak at at least -12dB
|
|
// -30dB aprox. 1.15V Oscilloscope -> normally 1.6V -> 1300 Points
|
|
// -16dB aprox. 1.27V Oscilloscope - normally 1.6V
|
|
// -18dB aprox 1.295V Oscilloscope -> use 1489 Points as decision line for sufficient Matching
|
|
|
|
int32_t findCurrentResonanceFrequency(uint32_t start_frequency, uint32_t stop_frequency, uint32_t frequency_step){
|
|
int minimum_reflection = 4096;
|
|
int current_reflection = 0;
|
|
uint32_t minimum_frequency = 0;
|
|
|
|
adf4351.setf(start_frequency); // A frequency value needs to be set once -> there seems to be a bug with the first SPI call
|
|
|
|
for(uint32_t frequency = start_frequency; frequency <= stop_frequency; frequency += frequency_step){
|
|
adf4351.setf(frequency);
|
|
delay(5); // This delay is essential! There is a glitch with ADC2 that leads to wrong readings if GPIO27 is set to high for multiple microseconds.
|
|
|
|
current_reflection = analogRead(REFLECTION_PIN);
|
|
|
|
if (current_reflection < minimum_reflection){
|
|
minimum_frequency = frequency;
|
|
minimum_reflection = current_reflection;
|
|
}
|
|
|
|
}
|
|
return minimum_frequency;
|
|
}
|
|
|
|
|
|
// Approximates the target frequency to about 3 MHZ with the tuning capacitor .... works so far
|
|
int32_t approximateResonance(uint32_t target_frequency, uint32_t current_resonance_frequency){
|
|
|
|
int32_t delta_frequency = target_frequency - current_resonance_frequency;
|
|
int rotation = 0; // rotation == 1 -> clockwise, rotation == -1 -> counterclockwise
|
|
|
|
if (delta_frequency < 0) rotation = -1; // negative delta means currentresonance is to high, hence anticlockwise movement is necessary
|
|
else rotation = 1;
|
|
|
|
tuning_stepper.moveTo(STEPS_PER_ROTATION * rotation);
|
|
tuning_stepper.runToPosition();
|
|
//step_n(STEPS_PER_ROTATION);
|
|
|
|
// @ Optimization possibility: -> just scan plausible area, would reduce half the scan time
|
|
int32_t one_revolution_resonance = findCurrentResonanceFrequency(current_resonance_frequency - 30000000U, current_resonance_frequency + 30000000U, FREQUENCY_STEP);
|
|
//Serial.println(one_revolution_resonance);
|
|
|
|
int32_t delta_one_revolution_frequency = one_revolution_resonance - current_resonance_frequency;
|
|
|
|
//Serial.println(delta_one_revolution_frequency);
|
|
//Serial.println(float) delta_frequency / (float) delta_one_revolution_frequency);
|
|
|
|
int32_t steps_to_delta_frequency = ((float) delta_frequency / (float) delta_one_revolution_frequency) * STEPS_PER_ROTATION * rotation;
|
|
|
|
tuning_stepper.moveTo(steps_to_delta_frequency);
|
|
tuning_stepper.runToPosition();
|
|
//step_n(STEPS_PER_ROTATION - steps_to_delta_frequency);
|
|
|
|
current_resonance_frequency = findCurrentResonanceFrequency(target_frequency - 5000000U, target_frequency + 5000000U, FREQUENCY_STEP);
|
|
return(current_resonance_frequency);
|
|
|
|
}
|
|
|
|
|
|
// Tries out different capacitor position until iteration depth is reached OR current_resonancy frequency matches the target_frequency
|
|
int32_t bruteforceResonance(uint32_t target_frequency, uint32_t current_resonance_frequency){
|
|
// Change Tuning Stepper -> Clockwise => Freq goes up
|
|
// Dir = 0 => Anticlockwise movement
|
|
int rotation = 0; // rotation == 1 -> clockwise, rotation == -1 -> counterclockwise
|
|
|
|
int ITERATIONS = 25; // Iteration depth
|
|
int iteration_steps = 0;
|
|
|
|
int32_t delta_frequency = target_frequency - current_resonance_frequency;
|
|
|
|
if (delta_frequency < 0) rotation = -1; // negative delta means currentresonance is too high, hence anticlockwise movement is necessary
|
|
else rotation = 1;
|
|
|
|
iteration_steps = rotation * (STEPS_PER_ROTATION / 50);
|
|
|
|
//'bruteforce' the stepper position to match the target frequency
|
|
|
|
for (int i = 0; i < ITERATIONS; i ++){
|
|
tuning_stepper.move(iteration_steps);
|
|
tuning_stepper.runToPosition();
|
|
|
|
// @ Optimization possibility: Reduce frequency range when close to target_frequency
|
|
current_resonance_frequency = findCurrentResonanceFrequency(target_frequency - 5000000U, target_frequency + 5000000U, FREQUENCY_STEP / 2);
|
|
|
|
//Serial.println(current_resonance_frequency);
|
|
//Serial.println(rotation);
|
|
//Serial.println(iteration_steps);
|
|
|
|
// Stops the iteration if the minima matches the target frequency
|
|
if (current_resonance_frequency == target_frequency) break;
|
|
|
|
// This means the bruteforce resolution was too high and the resonance frequency overshoot
|
|
// therfore the turn direction gets inverted and the increment halfed
|
|
if ((current_resonance_frequency > target_frequency) && (rotation == 1)) {
|
|
rotation = -1;
|
|
iteration_steps /= 2;
|
|
iteration_steps *= rotation;
|
|
}
|
|
else if ((current_resonance_frequency < target_frequency) && (rotation == -1)){
|
|
rotation = 1;
|
|
iteration_steps /= 2;
|
|
iteration_steps *= -rotation;
|
|
}
|
|
|
|
}
|
|
|
|
return current_resonance_frequency;
|
|
|
|
}
|
|
|
|
//
|
|
int optimizeMatching(uint32_t current_frequency){
|
|
int minimum_reflection = 4096;
|
|
int current_reflection = 0;
|
|
int minimum_matching_position = 0;
|
|
|
|
int ITERATIONS = 25; // //100 equals one full rotation
|
|
int iteration_steps = 0;
|
|
|
|
iteration_steps = STEPS_PER_ROTATION / 100;
|
|
|
|
|
|
for (int i = 0; i < ITERATIONS; i ++){
|
|
matching_stepper.move(iteration_steps);
|
|
matching_stepper.runToPosition();
|
|
|
|
for (uint32_t frequency = current_frequency - 5000000U; frequency < current_frequency + 5000000U; frequency += FREQUENCY_STEP){
|
|
adf4351.setf(frequency);
|
|
delay(10);
|
|
|
|
current_reflection = analogRead(REFLECTION_PIN);
|
|
|
|
if (current_reflection < minimum_reflection){
|
|
minimum_matching_position = matching_stepper.currentPosition();
|
|
minimum_reflection = current_reflection;
|
|
}
|
|
}
|
|
}
|
|
|
|
matching_stepper.moveTo(minimum_matching_position);
|
|
matching_stepper.run();
|
|
|
|
return (minimum_reflection);
|
|
}
|