The waveform generator is now configurable by the serial interface and meas script

This commit is contained in:
Kai Lauterbach 2024-02-12 11:07:33 +01:00
parent 56f8161e99
commit aa74f4e281
5 changed files with 193 additions and 25 deletions

View file

@ -55,6 +55,10 @@ uint8_t cc_commands[] = {
CC_CMD_SAV_DFLT, CC_CMD_SAV_DFLT,
CC_CMD_SET_CLK_CORR, CC_CMD_SET_CLK_CORR,
CC_CMD_GET_CLK_CORR, CC_CMD_GET_CLK_CORR,
CC_CMD_SET_WF_FREQ,
CC_CMD_SET_WF,
CC_CMD_SET_WF_DC,
CC_CMD_EN_WF,
}; };
void (*cc_cmd_functions[])() = { void (*cc_cmd_functions[])() = {
@ -70,6 +74,10 @@ void (*cc_cmd_functions[])() = {
CC_CMD_SAV_DFLT_FUNC, CC_CMD_SAV_DFLT_FUNC,
CC_CMD_SET_CLK_CORR_FUNC, CC_CMD_SET_CLK_CORR_FUNC,
CC_CMD_GET_CLK_CORR_FUNC, CC_CMD_GET_CLK_CORR_FUNC,
CC_CMD_SET_WF_FREQ_FUNC,
CC_CMD_SET_WF_FUNC,
CC_CMD_SET_WF_DC_FUNC,
CC_CMD_SET_EN_WF_FUNC,
}; };
uint8_t cc_cmd_data_to_read[] = { uint8_t cc_cmd_data_to_read[] = {
@ -85,6 +93,10 @@ uint8_t cc_cmd_data_to_read[] = {
CC_CMD_SAV_DFLT_DATA_TO_READ, CC_CMD_SAV_DFLT_DATA_TO_READ,
CC_CMD_SET_CLK_CORR_DATA_TO_READ, CC_CMD_SET_CLK_CORR_DATA_TO_READ,
CC_CMD_GET_CLK_CORR_DATA_TO_READ, CC_CMD_GET_CLK_CORR_DATA_TO_READ,
CC_CMD_SET_WF_FREQ_DATA_TO_READ,
CC_CMD_SET_WF_DATA_TO_READ,
CC_CMD_SET_WF_DC_DATA_TO_READ,
CC_CMD_SET_EN_WF_DATA_TO_READ,
}; };
uint8_t cc_read_data[CC_READ_DATA_MAX]; uint8_t cc_read_data[CC_READ_DATA_MAX];
@ -226,12 +238,21 @@ void cc_startMeasurement()
uint32_t a1_sum = 0; uint32_t a1_sum = 0;
uint16_t i = 0; uint16_t i = 0;
if (freq < 8000) // TODO an diesem punkt muss unterschieden werden ob eine waveform ausgegeben werden soll oder eine frequenz, und welche Art von Kurve
if (freq < WF_FREQ_MAX_HZ)
{ {
setWaveformFrequency(freq); if (freq > PWM_MAX_VALUE)
setWaveform(WAVEFORM_SINUS); {
setWaveform(WAVEFORM_SINUS);
setWaveformFrequency(freq);
} else {
setWaveform(WAVEFORM_DUTYCYCLE);
setWaveformDC((uint8_t)(freq & 0xff));
}
enableWaveformOutput(); enableWaveformOutput();
pollWaveformGenerator(); // manually poll the waveformgenerator
si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0 si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0
delay(1);
} else { } else {
disableWaveformOutput(); disableWaveformOutput();
si5351.set_freq((uint64_t)freq * 100, SI5351_PLL_FIXED, SI5351_CLK0); si5351.set_freq((uint64_t)freq * 100, SI5351_PLL_FIXED, SI5351_CLK0);
@ -269,6 +290,7 @@ void cc_startMeasurement()
send16BitValue(a1_sum); send16BitValue(a1_sum);
sendEOM(); sendEOM();
disableWaveformOutput();
si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0 si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0
if (freq >= end_freq) if (freq >= end_freq)
@ -304,9 +326,16 @@ void cc_enableClk(void)
sendSOM(); sendSOM();
if (cc_read_data[0] == SI5351_CLK0) if (cc_read_data[0] == SI5351_CLK0)
{ {
if (start_freq < 8000) if (start_freq < WF_FREQ_MAX_HZ) // < 8kHz
{ {
setWaveformFrequency(start_freq); if (start_freq > PWM_MAX_VALUE) // > 8 bit pwm value
{
setWaveform(WAVEFORM_SINUS);
setWaveformFrequency(start_freq);
} else {
setWaveform(WAVEFORM_DUTYCYCLE);
setWaveformDC((uint8_t)(start_freq & 0xff));
}
enableWaveformOutput(); enableWaveformOutput();
si5351.output_enable(SI5351_CLK0, 0); si5351.output_enable(SI5351_CLK0, 0);
} else { } else {
@ -394,6 +423,54 @@ void cc_getClkCorrection(void)
sendEOM(); sendEOM();
} }
void cc_setWFFreq(void)
{
uint16_t tmp_freq = read16BitDataFromBuffer(0);
setWaveformFrequency(tmp_freq);
sendSOM();
Serial.write(MSG_TYPE_ANSWER_OK);
sendEOM();
}
void cc_setWF(void)
{
uint8_t tmp_wf = cc_read_data[0];
setWaveform(tmp_wf);
sendSOM();
Serial.write(MSG_TYPE_ANSWER_OK);
sendEOM();
}
void cc_setWFDC(void)
{
uint8_t tmp_dc = cc_read_data[0];
setWaveformDC(tmp_dc);
sendSOM();
Serial.write(MSG_TYPE_ANSWER_OK);
sendEOM();
}
void cc_enableWF(void)
{
uint8_t tmp_en = cc_read_data[0];
if (tmp_en == 0)
{
disableWaveformOutput();
} else {
enableWaveformOutput();
}
sendSOM();
Serial.write(MSG_TYPE_ANSWER_OK);
sendEOM();
}
/*****************************************************************************/ /*****************************************************************************/
void cc_init() void cc_init()

View file

@ -1,6 +1,16 @@
/*****************************************************************************/ /*****************************************************************************/
#define WF_FREQ_MAX_HZ 8000
/*****************************************************************************/
#define PWM_BIT_WIDTH 8
#define PWM_PIN 5 // PWM-Pin für DAC0 auf dem Arduino Nano 328
#define PWM_MAX_VALUE ((1 << PWM_BIT_WIDTH)-1)
/*****************************************************************************/
#define MEAS_LOOP_CNT 20 #define MEAS_LOOP_CNT 20
#define MAIN_LOOP_DELAY_US 63 // 1/63us = ~16kHz #define MAIN_LOOP_DELAY_US 63 // 1/63us = ~16kHz
@ -49,6 +59,10 @@
#define CC_CMD_SAV_DFLT 0x22 #define CC_CMD_SAV_DFLT 0x22
#define CC_CMD_SET_CLK_CORR 0x23 #define CC_CMD_SET_CLK_CORR 0x23
#define CC_CMD_GET_CLK_CORR 0x24 #define CC_CMD_GET_CLK_CORR 0x24
#define CC_CMD_SET_WF_FREQ 0x30
#define CC_CMD_SET_WF 0x31
#define CC_CMD_SET_WF_DC 0x32
#define CC_CMD_EN_WF 0x33
/*****************************************************************************/ /*****************************************************************************/
@ -64,6 +78,10 @@
#define CC_CMD_SAV_DFLT_FUNC &cc_saveDefaults #define CC_CMD_SAV_DFLT_FUNC &cc_saveDefaults
#define CC_CMD_SET_CLK_CORR_FUNC &cc_setClkCorrection #define CC_CMD_SET_CLK_CORR_FUNC &cc_setClkCorrection
#define CC_CMD_GET_CLK_CORR_FUNC &cc_getClkCorrection #define CC_CMD_GET_CLK_CORR_FUNC &cc_getClkCorrection
#define CC_CMD_SET_WF_FREQ_FUNC &cc_setWFFreq
#define CC_CMD_SET_WF_FUNC &cc_setWF
#define CC_CMD_SET_WF_DC_FUNC &cc_setWFDC
#define CC_CMD_SET_EN_WF_FUNC &cc_enableWF
/*****************************************************************************/ /*****************************************************************************/
@ -79,6 +97,10 @@
#define CC_CMD_SAV_DFLT_DATA_TO_READ 0 #define CC_CMD_SAV_DFLT_DATA_TO_READ 0
#define CC_CMD_SET_CLK_CORR_DATA_TO_READ 4 #define CC_CMD_SET_CLK_CORR_DATA_TO_READ 4
#define CC_CMD_GET_CLK_CORR_DATA_TO_READ 0 #define CC_CMD_GET_CLK_CORR_DATA_TO_READ 0
#define CC_CMD_SET_WF_FREQ_DATA_TO_READ 2
#define CC_CMD_SET_WF_DATA_TO_READ 1
#define CC_CMD_SET_WF_DC_DATA_TO_READ 1
#define CC_CMD_SET_EN_WF_DATA_TO_READ 1
/*****************************************************************************/ /*****************************************************************************/

View file

@ -1,17 +1,16 @@
#include "Waveforms.h" #include "Waveforms.h"
#define PWM_BIT_WIDTH 8 uint8_t wf_wave0 = 0;
#define PWM_PIN 5 // PWM-Pin für DAC0 auf dem Arduino Nano 328 uint8_t wf_pos = 0;
uint16_t wf_freq = 0;
uint8_t wf_wave0 = 0; uint8_t wf_dutyCycle = 0;
uint8_t wf_pos = 0;
uint16_t wf_freq = 0;
unsigned long wf_sample_us = 0; unsigned long wf_sample_us = 0;
unsigned long wf_prevMicros = 0; unsigned long wf_prevMicros = 0;
bool wf_outputEnabled = true; // Variable to control waveform output state bool wf_outputEnabled = true; // Variable to control waveform output state
bool wf_pwm_needs_disabling = true;
void initWaveformGenerator() void initWaveformGenerator()
{ {
@ -19,22 +18,24 @@ void initWaveformGenerator()
setWaveform(WAVEFORM_SINUS); setWaveform(WAVEFORM_SINUS);
// Call the function to set default frequency, here you might want to specify a default frequency // Call the function to set default frequency, here you might want to specify a default frequency
setWaveformFrequency(WAVEFORM_DEFAULT_FREQ_HZ); setWaveformFrequency(WAVEFORM_DEFAULT_FREQ_HZ);
setWaveformDC(0);
analogWrite(PWM_PIN, 0);
} }
void setWaveform(uint8_t waveform0) void setWaveform(uint8_t waveform0)
{ {
if (waveform0 >= 0 and waveform0 < WAVEFORM_MAXWAVEFORM_NUM) if (waveform0 >= 0 and waveform0 < WAVEFORM_MAXWAVEFORM_NUM)
{ {
// Set default waveforms
wf_wave0 = waveform0; wf_wave0 = waveform0;
} else { } else {
// Set default waveforms
wf_wave0 = WAVEFORM_SINUS; wf_wave0 = WAVEFORM_SINUS;
} }
} }
void setWaveformFrequency(uint16_t frequency) void setWaveformFrequency(uint16_t frequency)
{ {
if (frequency >= 1 and frequency < 8000) if (frequency >= 1 and frequency < WF_FREQ_MAX_HZ)
{ {
wf_freq = frequency; wf_freq = frequency;
} else { } else {
@ -43,6 +44,11 @@ void setWaveformFrequency(uint16_t frequency)
wf_sample_us = 1000000UL / ((unsigned long)wf_freq * WAVEFORM_MAX_SAMPLES_NUM); wf_sample_us = 1000000UL / ((unsigned long)wf_freq * WAVEFORM_MAX_SAMPLES_NUM);
} }
void setWaveformDC(uint8_t dc)
{
wf_dutyCycle = dc;
}
void enableWaveformOutput() void enableWaveformOutput()
{ {
wf_outputEnabled = true; wf_outputEnabled = true;
@ -53,27 +59,48 @@ void disableWaveformOutput()
wf_outputEnabled = false; wf_outputEnabled = false;
} }
bool isWaveformEnabled()
{
return wf_outputEnabled;
}
void pollWaveformGenerator() void pollWaveformGenerator()
{ {
if (wf_outputEnabled) if (wf_outputEnabled)
{ {
unsigned long currentMicros = micros(); // Aktuelle Zeit abrufen
if (currentMicros - wf_prevMicros >= wf_sample_us) if (wf_wave0 != WAVEFORM_DUTYCYCLE)
{ {
wf_prevMicros = currentMicros; unsigned long currentMicros = micros(); // Aktuelle Zeit abrufen
if (currentMicros - wf_prevMicros >= wf_sample_us)
{
wf_prevMicros = currentMicros;
uint16_t sample = map(waveformsTable[wf_wave0][wf_pos], 0, 0xfff, 0, (1 << PWM_BIT_WIDTH)-1); uint16_t sample = map(waveformsTable[wf_wave0][wf_pos], 0, 0xfff, 0, PWM_MAX_VALUE);
sample = constrain(sample, 0, (1 << PWM_BIT_WIDTH)-1); sample = constrain(sample, 0, PWM_MAX_VALUE);
analogWrite(PWM_PIN, sample); // write the selected waveform on DAC0 // TODO write the selected waveform on DAC0
// analogWrite(PWM_PIN, 128); // write the selected waveform on DAC0 analogWrite(PWM_PIN, sample);
wf_pos++; wf_pos++;
if (wf_pos == WAVEFORM_MAX_SAMPLES_NUM) // Reset the counter to repeat the wave if (wf_pos == WAVEFORM_MAX_SAMPLES_NUM) // Reset the counter to repeat the wave
wf_pos = 0; wf_pos = 0;
}
} else {
// WAVEFORM_DUTYCYCLE
if (analogRead(PWM_PIN) != wf_dutyCycle)
analogWrite(PWM_PIN, wf_dutyCycle);
} }
if (!wf_pwm_needs_disabling)
wf_pwm_needs_disabling = true;
} else { } else {
analogWrite(PWM_PIN, 0); if (wf_pwm_needs_disabling)
{
analogWrite(PWM_PIN, 0);
wf_pwm_needs_disabling = false;
}
} }
} }

View file

@ -10,6 +10,7 @@
#define WAVEFORM_SINUS 0 #define WAVEFORM_SINUS 0
#define WAVEFORM_TRIANGULAR 1 #define WAVEFORM_TRIANGULAR 1
#define WAVEFORM_SAWTOOTH 2 #define WAVEFORM_SAWTOOTH 2
#define WAVEFORM_DUTYCYCLE 3
static int waveformsTable[WAVEFORM_MAXWAVEFORM_NUM][WAVEFORM_MAX_SAMPLES_NUM] = { static int waveformsTable[WAVEFORM_MAXWAVEFORM_NUM][WAVEFORM_MAX_SAMPLES_NUM] = {
// Sin wave // Sin wave

View file

@ -43,6 +43,14 @@ parser.add_argument("-c", "--get_config", default=False, help="", action='store_
parser.add_argument("-l", "--enable_clk", type=int, help="") parser.add_argument("-l", "--enable_clk", type=int, help="")
# disable clk # disable clk
parser.add_argument("-L", "--disable_clk", type=int, help="") parser.add_argument("-L", "--disable_clk", type=int, help="")
# enable/disable WaveForm
parser.add_argument("-W", "--enable_wf", type=int, help="")
# WaveForm form (0 sinus, 1 triangular, 2 sawtooth)
parser.add_argument("-w", "--form_wf", type=int, help="")
# WaveForm frequency (not related to PWM frequency)
parser.add_argument("-q", "--freq_wf", type=int, help="")
# WaveForm PWM duty cycle
parser.add_argument("-D", "--dc_wf", type=int, help="")
# save default config # save default config
parser.add_argument("-S", "--save_config", default=False, help="", action='store_true') parser.add_argument("-S", "--save_config", default=False, help="", action='store_true')
@ -75,6 +83,10 @@ CC_CMD_GET_CONFIG = 0x10
CC_CMD_EN_CLK = 0x20 CC_CMD_EN_CLK = 0x20
CC_CMD_DIS_CLK = 0x21 CC_CMD_DIS_CLK = 0x21
CC_CMD_SAV_DFLT = 0x22 CC_CMD_SAV_DFLT = 0x22
CC_CMD_SET_WF_FREQ = 0x30
CC_CMD_SET_WF = 0x31
CC_CMD_SET_WF_DC = 0x32
CC_CMD_EN_WF = 0x33
############################################################################### ###############################################################################
@ -626,6 +638,35 @@ if __name__ == "__main__":
sendSerialData([CC_CMD_DIS_CLK, args.disable_clk]) sendSerialData([CC_CMD_DIS_CLK, args.disable_clk])
dataSend = dataSend + 1 dataSend = dataSend + 1
if args.enable_wf != None:
if args.enable_wf < 0 or args.enable_wf > 1:
args.enable_wf = 0
print(("Disabling" if args.enable_wf == 0 else "Enabling") + " wave form output")
sendSerialData([CC_CMD_EN_WF, args.enable_wf])
dataSend = dataSend + 1
if args.form_wf != None:
if args.form_wf < 0 or args.form_wf > 3:
args.form_wf = 0
print("Wave form type is set to %d" % (args.form_wf))
sendSerialData([CC_CMD_SET_WF, args.form_wf])
dataSend = dataSend + 1
if args.freq_wf != None:
if args.freq_wf < 0 or args.freq_wf > 7999:
args.freq_wf = 0
print("Wave frequency set to %d" % (args.freq_wf))
sendSerialData([CC_CMD_SET_WF_FREQ, (args.freq_wf & 0x0000ff00) >> 8,
(args.freq_wf & 0x000000ff)])
dataSend = dataSend + 1
if args.dc_wf != None:
if args.dc_wf < 0 or args.dc_wf > 255:
args.dc_wf = 0
print("PWM duty cycle set to %d" % (args.dc_wf))
sendSerialData([CC_CMD_SET_WF_DC, args.dc_wf])
dataSend = dataSend + 1
if args.save_config == True: if args.save_config == True:
print("Save default configuration values...") print("Save default configuration values...")
sendSerialData([CC_CMD_SAV_DFLT]) sendSerialData([CC_CMD_SAV_DFLT])