Components and supplies
Project strip board, 19x31 holes
Rotating selector
Arduino Nano R3
AD9833
Graphic OLED, 128 x 64
Tools and machines
Plier, Long Nose
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Soldering iron (generic)
Multitool, Screwdriver
Apps and platforms
Arduino IDE
Project description
Code
Code
arduino
Arduino code for this project
1// ----------------------------------------------------------------- 2// A simple sine-square-triangle signal generator 3// Using GY-9833 frequency generator board, with OLED display. 4// 5// Pushbutton sets waveform; rotary encoder sets frequency 6// Range 10 Hz - 1 MHz 7// Michael Willems 8// Contact: michael@willems.ca 9// Date: 16/12/2022 10// ----------------------------------------------------------------- 11 12 13// ----------------------------------------------------------------------------------------- 14// DECLARATIONS: 15// ----------------------------------------------------------------------------------------- 16 17// Include the required Arduino libraries: 18#include <Wire.h> //for I2C 19#include <MD_AD9833.h> //for Frequency Generator 20#include <Encoder.h> //for Rotary Encoder 21 22// Pins for SPI comm with the AD9833 IC 23#define DATA 11 ///< SPI Data pin number 24#define CLK 13 ///< SPI Clock pin number 25#define FSYNC 10 ///< SPI Load pin number (FSYNC in AD9833 usage) 26MD_AD9833 AD(FSYNC); // Hardware SPI 27 28// Include the OLED stuff: 29#include <Adafruit_GFX.h> 30#include <Adafruit_SSD1306.h> 31#define SCREEN_WIDTH 128 // OLED display width, in pixels 32#define SCREEN_HEIGHT 64 // OLED display height, in pixels 33#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 34//#define SCREEN_ADDRESS 0x3C //< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 35#define SCREEN_ADDRESS 0x3C //< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 36Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 37 38//the rotary encoder: 39Encoder Knob(2,3); // The (interruptable) pins for "clock and data" 40long KnobPosition = 0; 41long newKnobPosition; 42 43//the rotator knob pushbutton: 44int button2 = 6; 45long buttonTimer2 = 0; 46long buttonActive2 = false; 47long longPressTime2 = 100; 48long longPressActive2 = false; 49 50// the regular (waveform select) button: 51int button=7; // for selecting waveform 52long buttonTimer = 0; // to see how long the button has been pressed 53boolean buttonActive = false; // to set if the button is currently pressed 54long longPressTime = 100; // How long to push button before we activate button mode? 55boolean longPressActive = false; 56 57// Other declarations: 58unsigned long counter; // for flashing on-board LED with 1s frequency 59int activeled = 12 ; // for heartbeat LED, if we bother to hook it up 60byte wavetype = 1; 61long Freq = 1000; // starting frequency 62byte oldWavetype = 0; 63long oldFreq = 0; 64char wavemode = 1; 65byte changepower = 0; 66long delta = 1; 67 68 69// ----------------------------------------------------------------------------------------- 70// THE SETUP (RUNS ONCE): 71// ----------------------------------------------------------------------------------------- 72// 73void setup() { 74 pinMode(activeled, OUTPUT); 75 pinMode(button,INPUT_PULLUP); //so making it negative activates the button 76 pinMode(button2,INPUT_PULLUP); //so making it negative activates the button 77 counter = millis(); 78 79 Serial.begin(9600); 80 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { //if display fails, stop 81 Serial.println("No display found"); 82 for(;;); 83 } 84 Serial.println("Display found OK"); 85 86 AD.begin(); // start the generator board 87 88 display.display(); // show OLED logo 89 delay(1000); 90 display.clearDisplay(); 91 display.display(); 92 display.setTextSize(2); // Draw 2X-scale text 93 display.setTextColor(SSD1306_WHITE); 94 display.setCursor(0,0); 95 display.println(F("SYSTEM")); 96 display.setCursor(0,20); 97 display.println(F("INITIATED")); 98 display.setCursor(0,40); 99 display.println(F("& READY")); 100 display.println(); 101 display.display(); 102 delay(1000); 103 display.clearDisplay(); 104 displaythelabels(); 105 AD.setMode(MD_AD9833::MODE_SINE); 106 AD.setFrequency(MD_AD9833::CHAN_0, Freq); 107} 108 109 110// ----------------------------------------------------------------------------------------- 111// THE LOOP: 112// ----------------------------------------------------------------------------------------- 113// 114void loop() { 115 // First, the "every half second" stuff: 116 if ((millis() - counter) > 500) { //was 500 117 digitalWrite (activeled,!(digitalRead(activeled))); //the heartbeat LED 118 displayvalues(wavetype, Freq, oldWavetype, oldFreq); //display if changes have occurred 119 counter = millis(); 120 } 121 122 // Now the "always" part of the loop: 123 124 // Now check the WAVETYPE button: is it pressed? If so, then change wavetype 125 if (digitalRead(button) == LOW) { 126 if (buttonActive == false) { 127 buttonActive = true; 128 buttonTimer = millis(); // i.e. start the timer 129 } 130 if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) { 131 longPressActive = true; 132 //Now change the wavetype (1-2-3-4 is sine, triangle, square, off) 133 wavetype = wavetype+1; 134 if (wavetype>4){ 135 wavetype=1; 136 } 137 } 138 } else { 139 if (buttonActive == true) { 140 if (longPressActive == true) { 141 longPressActive = false; 142 } 143 } 144 buttonActive = false; 145 } 146 147 // Now check the CONTROLLER button: is it pressed? If so, change delta effected by turning rotator knob. 148 if (digitalRead(button2) == LOW) { 149 if (buttonActive2 == false) { 150 buttonActive2 = true; 151 buttonTimer2 = millis(); // i.e. start the timer 152 } 153 if ((millis() - buttonTimer2 > longPressTime2) && (longPressActive2 == false)) { 154 longPressActive2 = true; 155 //Here, do the things you need to do to set the delta: 156 changepower = changepower + 1; // meaning delta is 10^changepower 157 if (changepower>5){ 158 changepower=0; 159 } 160 switch (changepower) { 161 case 0: delta = 1; break; 162 case 1: delta = 10; break; 163 case 2: delta = 100; break; 164 case 3: delta = 1000; break; 165 case 4: delta = 10000; break; 166 case 5: delta = 100000; break; 167 } 168 // now display the new delta (change amount per click): 169 display.fillRect(65, 20, 35, 15, 0); 170 display.setTextSize(1); 171 display.setCursor(65,20); 172 display.println(delta); 173 display.display(); 174 } 175 } else { 176 if (buttonActive2 == true) { 177 if (longPressActive2 == true) { 178 longPressActive2 = false; 179 } 180 } 181 buttonActive2 = false; 182 } 183 184 // read the knob position. Has it changed? Then change frequency 185 // by the delta amount set by the controller pushbutton (1 Hz, 10 Hz, 100 Hz, etc) 186 newKnobPosition = Knob.read()/4; 187 if (newKnobPosition != KnobPosition) { 188 Freq = Freq + (newKnobPosition * delta) - (KnobPosition * delta); 189 if (Freq<10) { 190 Freq=10; 191 } 192 KnobPosition = newKnobPosition; 193 } 194 195} // end of loop 196 197// ----------------------------------------------------------------------------------------- 198// THE FUNCTIONS: 199// ----------------------------------------------------------------------------------------- 200 201void displaythelabels() { 202 display.clearDisplay(); 203 display.display(); 204 display.setTextSize(1); 205 display.display(); 206 // the display values stuff: 207 display.drawRect(21, 1, 100, 14, 1); 208 display.setTextColor(SSD1306_WHITE); 209 display.setCursor(24,5); 210 display.println(F("MVW SigGen 1.0")); 211 display.setTextColor(SSD1306_WHITE); 212 // now delta and type and frequency labels: 213 display.setCursor(24,20); 214 display.println(F("Delta: 1")); 215 display.setCursor(24,35); 216 display.println(F("Type : ")); 217 display.setCursor(24,50); 218 display.println(F("Freq : ")); 219 //and now activate it all! 220 display.display(); 221} 222 223void displayvalues(byte W, long F, byte OW, long OF){ 224String wavestring; 225 //show only changed type/freq: 226 if ((F != OF) || (W != OW)) { 227 display.setTextSize(1); 228 display.fillRect(65, 35, 50, 25, 0); 229 display.setCursor(65,35); 230 switch (W) { 231 case 1: wavestring = "Sine"; break; 232 case 2: wavestring = "Triangle"; break; 233 case 3: wavestring = "Square"; break; 234 case 4: wavestring = "Off"; break; 235 } 236 display.println(wavestring); 237 display.setCursor(65,50); 238 display.println(Freq); 239 display.display(); 240 //Now change the chip output waveform: 241 switch (W) { 242 case 1: wavemode = MD_AD9833::MODE_SINE; break; 243 case 2: wavemode = MD_AD9833::MODE_TRIANGLE; break; 244 case 3: wavemode = MD_AD9833::MODE_SQUARE1; break; 245 case 4: wavemode = MD_AD9833::MODE_OFF; break; 246 } 247 AD.setMode(wavemode); 248 AD.setFrequency(MD_AD9833::CHAN_0, Freq); 249 oldWavetype = wavetype; 250 oldFreq = Freq; 251 delay(50); 252 } 253} 254 255
Downloadable files
Circuit Diagram
Circuit Diagram
Manual
The (pretty essential) manual
Manual
Comments
Only logged in users can leave comments