Arduino DDS
Moderátor: Moderátoři
Arduino DDS
* AD9833 Function Generator
* By John Bradnam
* based on:
* DIY Function/Waveform Generator by GreatScottLab
* (https://www.instructables.com/DIY-Funct ... Generator/)
*
* 230114 - Rewrote code
*/
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include "AD9833.h"
#include "Rotary.h"
//Pins
#define ROTARY_A 2
#define ROTARY_B 3
#define SWITCH A3
#define led 12
#define AD9833_FSYNC 10
#define AD9833_SCLK 13
#define AD9833_SDATA 11
//Modules
AD9833 sigGen(AD9833_FSYNC, 24000000);// Initialise our AD9833 with FSYNC and a master clock frequency of 24MHz
LiquidCrystal_I2C lcd(0x27, 16, 2);
Rotary encoder(ROTARY_A, ROTARY_B); // Initialise the encoder on pins 2 and 3 (interrupt pins)
enum MenuEnum { X1, X10, X100, X1K, X10K, X100K, X1M, WAVEFORM };
enum WaveEnum { SINE, TRANGLE, SQUARE };
#define MENU_TEXT_LEN 10
const String menuText[] = {"x 1 Hz", "x 10 Hz", "x 100 Hz","x 1 kHz", "x 10 kHz", "x 100 kHz", "x 1 MHz", "Waveform"};
const String waveText[] = {" Sinus", "Triang", "Square"};
//EEPROM handling
//Uncomment next line to clear out EEPROM and reset
//#define RESET_EEPROM
#define EEPROM_ADDRESS 0
#define EEPROM_MAGIC 0x0BAD0DAD
typedef struct {
uint32_t magic;
MenuEnum menuState;
WaveEnum waveState;
long frequency;
} EEPROM_DATA;
EEPROM_DATA EepromData; //Current EEPROM settings
#define EEPROM_UPDATE_TIME 60000 //Check for eprom update every minute
unsigned long eepromTimeout = 0;
bool eepromUpdate = false;
#define FREQ_MAX 5000000
volatile bool updateDisplay = false;
//--------------------------------------------------------------------
//Setup hardware
void setup()
{
lcd.init();
lcd.backlight();
digitalWrite(led,LOW);
//Serial.begin(57600);
//Serial.println("Starting...");
//Get last settings
readEepromData();
// Initialise the LCD, start the backlight and print a "bootup" message for two seconds
lcd.begin(16, 2);
lcd.print(" === AD9833 === ");
lcd.setCursor(0, 1);
lcd.print("Signal Generator");
delay(2000);
// Display initial set values
lcd.clear();
displayFrequency();
displayMenu();
displayWaveform();
// Initialise the AD9833 with 1KHz sine output, no phase shift for both
// registers and remain on the FREQ0 register
// sigGen.lcdDebugInit(&lcd);
sigGen.reset(1);
sigGen.setFreq(EepromData.frequency);
sigGen.setPhase(0);
sigGen.setFPRegister(1);
sigGen.setFreq(EepromData.frequency);
sigGen.setPhase(0);
sigGen.setFPRegister(0);
sigGen.mode((int)EepromData.waveState);
sigGen.reset(0);
// Set pins A and B from encoder as interrupts
attachInterrupt(digitalPinToInterrupt(ROTARY_A), encChange, CHANGE);
attachInterrupt(digitalPinToInterrupt(ROTARY_B), encChange, CHANGE);
// Initialise pin as input with pull-up enabled and debounce variable for
// encoder button
pinMode(SWITCH, INPUT_PULLUP);
pinMode (led,OUTPUT);
// Set Cursor to initial possition
lcd.setCursor(0, 1);
eepromTimeout = millis() + EEPROM_UPDATE_TIME;
}
//--------------------------------------------------------------------
//Main loop
void loop()
{
// If button is pressed, change the menu
if (testButton(true))
{
EepromData.menuState = (EepromData.menuState == WAVEFORM) ? X1 : (MenuEnum)((int)EepromData.menuState + 1);
eepromUpdate = true;
updateDisplay = true;
}
// Update display if needed
if (updateDisplay)
{
displayFrequency();
displayMenu();
displayWaveform();
updateDisplay = false;
}
//Update EEPROM if settings changed
if (millis() > eepromTimeout)
{
if (eepromUpdate)
{
writeEepromData();
eepromUpdate = false;
}
eepromTimeout = millis() + EEPROM_UPDATE_TIME;
}
}
//--------------------------------------------------------------------
// Test if button has been pressed
// waitForRelease - True to wait until button gos up
// Returns true if button is pressed
bool testButton(bool waitForRelease)
{
bool pressed = false;
if (digitalRead(SWITCH) == LOW)
{
pressed = true;
while (waitForRelease && digitalRead(SWITCH) == LOW)
{
yield();
}
}
return pressed;
}
//--------------------------------------------------------------------
// Encoder has been rotated
// Change frequency or waveform based on menu selection
void encChange()
{
unsigned char state = encoder.process();
if (state != DIR_NONE)
{
switch (EepromData.menuState)
{
case X1: updateFrequency(state,1); break;
case X10: updateFrequency(state,10); break;
case X100: updateFrequency(state,100); break;
case X1K: updateFrequency(state,1000); break;
case X10K: updateFrequency(state,10000); break;
case X100K: updateFrequency(state,100000); break;
case X1M: updateFrequency(state,1000000); break;
case WAVEFORM: updateWaveform(state); break;
}
}
}
//--------------------------------------------------------------------
//Change the current frequency based on menu and stepValue
// state - Either DIR_CW or DIR_CCW
// stepValue - Current amount to change frequency by
void updateFrequency(unsigned char state, long stepValue)
{
bool update = false;
long old = EepromData.frequency;
if (state == DIR_CW)
{
EepromData.frequency = min(EepromData.frequency + stepValue,FREQ_MAX);
}
else
{
EepromData.frequency = max(EepromData.frequency - stepValue,0);
}
if (old != EepromData.frequency)
{
sigGen.setFreq(EepromData.frequency);
eepromUpdate = true;
updateDisplay = true;
}
}
//--------------------------------------------------------------------
//Change the current waveform
// state - Either DIR_CW or DIR_CCW
void updateWaveform(unsigned char state)
{
if (state == DIR_CW)
{
EepromData.waveState = (EepromData.waveState == SQUARE) ? SINE : (WaveEnum)((int)EepromData.waveState + 1);
}
else
{
EepromData.waveState = (EepromData.waveState == SINE) ? SQUARE : (WaveEnum)((int)EepromData.waveState - 1);
}
sigGen.mode((int)EepromData.waveState);
eepromUpdate = true;
updateDisplay = true;
}
//--------------------------------------------------------------------
//Display current frequency
void displayFrequency()
{
lcd.setCursor(0, 0);
lcd.print(formatNumber(EepromData.frequency,"F: "," Hz",16));
}
//--------------------------------------------------------------------
//Display active menu state
void displayMenu()
{
lcd.setCursor(0, 1);
lcd.print(padString(menuText[(int)EepromData.menuState],MENU_TEXT_LEN));
}
//--------------------------------------------------------------------
//Display active waveform
void displayWaveform()
{
lcd.setCursor(10, 1);
lcd.print(waveText[(int)EepromData.waveState]);
}
//-----------------------------------------------------------------------------------
//Display a number with comma seperators
// number - number to format
// prefix - String to prefix number with
// postfix - String to append to number
// pad - Add spaces to the right pad string
// returns String with formatted number
String formatNumber(long number, String prefix, String postfix, int pad)
{
String s = "";
bool space = true;
for (uint8_t i = 0; i < 8; i++)
{
if ((i==3 || i==6) && !space && number > 0)
{
s = String(',') + s;
}
if (number > 0 || i == 0)
{
s = String((char)((number % 10) + 48)) + s;
space = false;
}
else
{
space = true;
}
number = number / 10;
}
s = prefix + s + postfix;
return padString(s, pad);
}
//-----------------------------------------------------------------------------------
//Pad string with spaces
// s - string to pad
// prefix - String to prefix number with
// returns padded String
String padString(String s, int pad)
{
String sOut = String(s);
int len = pad - s.length();
for (uint8_t i = 0; i < len; i++)
{
sOut += ' ';
}
return sOut;
}
//--------------------------------------------------------------------
//Write the EepromData structure to EEPROM
void writeEepromData(void)
{
//This function uses EEPROM.update() to perform the write, so does not rewrites the value if it didn't change.
EEPROM.put(EEPROM_ADDRESS,EepromData);
}
//--------------------------------------------------------------------
//Read the EepromData structure from EEPROM, initialise if necessary
void readEepromData(void)
{
#ifndef RESET_EEPROM
EEPROM.get(EEPROM_ADDRESS,EepromData);
if (EepromData.magic != EEPROM_MAGIC)
{
#endif
EepromData.magic = EEPROM_MAGIC;
EepromData.menuState = WAVEFORM;
EepromData.waveState = SINE;
EepromData.frequency = 1000;
writeEepromData();
#ifndef RESET_EEPROM
}
#endif
}][/code]
- Přílohy
-
signalgeneratorv3_.txt- (8.87 KiB) Staženo 115 x
- Dumitru
- Příspěvky: 254
- Registrován: 11 pro 2015, 00:00
- Bydliště: Slovensko,Bratislava
- Kontaktovat uživatele:
Kód: Vybrat vše
void updateWaveform(unsigned char state)
{
if (state == DIR_CW)
{
EepromData.waveState = (EepromData.waveState == SQUARE) ? SINE : (WaveEnum)((int)EepromData.waveState + 1);
}
else
{
EepromData.waveState = (EepromData.waveState == SINE) ? SQUARE : (WaveEnum)((int)EepromData.waveState - 1);
}
sigGen.mode((int)EepromData.waveState);
eepromUpdate = true;
updateDisplay = true;
}
stačí dať jeden if
nejak takto
Kód: Vybrat vše
void updateWaveform(unsigned char state)
{
if (state == DIR_CW)
{
EepromData.waveState = (EepromData.waveState == SQUARE) ? SINE : (WaveEnum)((int)EepromData.waveState + 1);
}
else
{
EepromData.waveState = (EepromData.waveState == SINE) ? SQUARE : (WaveEnum)((int)EepromData.waveState - 1);
}
sigGen.mode((int)EepromData.waveState);
if (EepromData.waveState == SQUARE)
{
// zapni D12 príkaz neviem :D
}
else
{
// vypni D12
}
eepromUpdate = true;
updateDisplay = true;
}
- pocitujlasku
- Příspěvky: 2764
- Registrován: 12 pro 2005, 00:00
- Bydliště: SR, Poprad
void updateWaveform(unsigned char state)
{
if (state == DIR_CW)
{
EepromData.waveState = (EepromData.waveState == SQUARE) ? SINE : (WaveEnum)((int)EepromData.waveState + 1);
}
else
{
EepromData.waveState = (EepromData.waveState == SINE) ? SQUARE : (WaveEnum)((int)EepromData.waveState - 1);
}
digitalWrite(D12, EepromData.waveState == SQUARE?HIGH:LOW);
sigGen.mode((int)EepromData.waveState);
eepromUpdate = true;
updateDisplay = true;
}
}
- Dumitru
- Příspěvky: 254
- Registrován: 11 pro 2015, 00:00
- Bydliště: Slovensko,Bratislava
- Kontaktovat uživatele:
https://www.tutorialspoint.com/arduino/ ... e%20state.
že by takto
Kód: Vybrat vše
void setup () {
pinMode(D12 , OUTPUT); // set the digital pin as output
}
- pocitujlasku
- Příspěvky: 2764
- Registrován: 12 pro 2005, 00:00
- Bydliště: SR, Poprad
//--------------------------------------------------------------------
//Change the current waveform
// state - Either DIR_CW or DIR_CCW
void updateWaveform(unsigned char state)
{
if (state == DIR_CW)
{
EepromData.waveState = (EepromData.waveState == SQUARE) ? SINE : (WaveEnum)((int)EepromData.waveState + 1);
digitalWrite(led, EepromData.waveState == SQUARE?HIGH:LOW);
}
else
{
EepromData.waveState = (EepromData.waveState == SINE) ? SQUARE : (WaveEnum)((int)EepromData.waveState - 1);
digitalWrite(led, EepromData.waveState == SQUARE?HIGH:LOW);
}
sigGen.mode((int)EepromData.waveState);
eepromUpdate = true;
updateDisplay = true;
}
Teraz to funguje. VEĽKA VĎAKA.
Ešte by som poprosil ten druhý.
Zkus zakomentovat jeden z řádků:jankrizan píše: Ešte by som poprosil ten druhý.
Kód: Vybrat vše
attachInterrupt(digitalPinToInterrupt(ROTARY_A), encChange, CHANGE);
attachInterrupt(digitalPinToInterrupt(ROTARY_B), encChange, CHANGE);
Proč mi nemůže všechno chodit hned ?!!
- Přílohy
-
DDS_function_generator_.txt- (6.93 KiB) Staženo 94 x