استخدم Arduino وشاشة OLED ووحدة AD9833 DDS لإنشاء مولد موجات مفيد لمختبرك.
الأشياء المستخدمة في هذا المشروع
اردوينو ناونو
شاشة Display SH1106 I2C Oled 128x64 pixel (4 pin)
AD9833 DDS Module
مقاومة متغيرة
ريلي 5 فولت
مكثف 10 µF
مكثف Polyester capacitor 10 nF
قصة
لقد تأجلت لفترة طويلة شراء راسم الذبذبات. الآن ، بعد شرائه ، حان الوقت أيضًا للحصول على مولد إشارة غير مكلف للاستخدام في هواية ، وهو ضروري لتشخيص الدوائر الصوتية والمزيد. من خلال الجمع بين شغفي الإلكترونيات والحوسبة ، فإن أفضل شيء هو القيام بذلك بنفسك باستخدام Arduino.
المميزات
تردد الخرج بين 1 هرتز و 999999 هرتز
وضعان لتغير التردد: لوغاريتمي ورقم واحد
ثلاثة أنواع من الموجة والجيب والمثلث والمربعة
AC أو DC اقتران الإخراج
القدرة على الكنس باستمرار بين قيمتين ترددات محددة مسبقًا
يتم التحكم فيها حصريًا بمقبض واحد
شاشة توقف مدمجة للحفاظ على عمر شاشة oled
#include "JXWG_Defs.h" #include "JXWG_Graphics.h" void setup() { //if you are using a simple encoder and 3x10K pullup resistors, apply this settings below pinMode(PinA, INPUT); pinMode(PinB, INPUT); pinMode(PinS, INPUT); //if you are using a simple encoder whitout 3x10K resistors use next tree row //pinMode(PinA, INPUT_PULLUP); //pinMode(PinB, INPUT_PULLUP); //pinMode(PinS, INPUT_PULLUP); //MOST PCB WELDED ENCODERS ALREADY HAVE PULLUP RESISTORS ON PIN A AND B BUT NOT ON SWITCH PIN //then use the settings below //pinMode(PinA, INPUT); //pinMode(PinB, INPUT); //pinMode(PinS, INPUT_PULLUP); digitalWrite(PinA, HIGH); digitalWrite(PinB, HIGH); digitalWrite(PinS, HIGH); pinMode(PinCoupling, OUTPUT); //Coupling Mode Encoder.setDebounceDelay(5); display.begin(SH1106_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (for the 128x64) display.clearDisplay(); //display.setRotation(2); //uncomment this line if you want to mount the display upside down Wire.begin(); // join i2c bus as master TWBR = 5; // freq=615kHz period=1.625uS //Assigns encoder switch push event to interrupt 1 Pin 3 of Arduino attachInterrupt(digitalPinToInterrupt(PinS), encoderSwitch, FALLING); DDS_Init(); //Initialize the DDS module; setConfig(); //Load config and set startup values } //---> end setup() void loop() { JX_WaveGenerator_MAIN(); } //----------------------------------------------------------------------------------------------------------------------------------------- // JX WaveGenerator MAIN function //----------------------------------------------------------------------------------------------------------------------------------------- void JX_WaveGenerator_MAIN() { byte encoderSpin = Encoder.rotate(); //Encoder rotation direction 1=CW, 2=CCW byte encoderLongPush = Encoder.pushLong(1000); //encoder long push event long lStep = 0; //current frequency step value long wTime = 600000; //10 min if (encoderPush) delay(250); if (encoderSpin) { cTime = millis(); } else { if (millis() - cTime > wTime) { ScreenSaver(); } } switch (mode) { case LOGARITHMIC: //0 //----------------------------------------------------------------------------------------------------------------------------------- // mode LOGARITHMIC: Encoder rotation change frequency in logaritmic step 1,10,100,1000,10000,100000 Hz //----------------------------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (lFreq >= 1) { lStep = AutoStep(lFreq, encoderSpin); //Calculate logaritmic step } else if (_CouplingMode == OFF) { //if coupling mode is set to OFF resetCouplingMode(); //set default coupling mode when Frequency is not 0 encoderSpin = 0; //skip first spin } if (encoderSpin == CW && lFreq <= 999999 - lStep) { //spin CW increment the frequency lFreq += lStep; } if (encoderSpin == CCW && lFreq >= lStep + 1) { //spin CCW decrement the frequency lFreq -= lStep; } DDS_FrequencySet(lFreq, Wave[_WaveType]); //send the frequency value to DDS module displayFrequency(lFreq); //send formatted freq to display lLastFreq = lFreq; //save current freq } //----------------------------------------------------------------------------------------------------------------------------------- // workmode LOGARITHMIC: Encoder push switch to OPTIONS mode //----------------------------------------------------------------------------------------------------------------------------------- if (encoderPush) { encoderPush = false; //Clear push flag drawSymbol(1); //draw arrow symbol selectIcon(0, WHITE); //draw a border around first icon idx = 0; idy = 0; //reset pointers var mode = OPTIONS; //go to mode OPTIONS } break; //end mode LOGARITHMIC case SINGLEDIGIT: //1 //------------------------------------------------------------------------------------------------------------- // submode SINGLEDIGIT: Encoder rotation move cursor left and right //------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idx < MAXDIGIT + 2) idx++; //clockwise increase pointer if (encoderSpin == CCW && idx > 0) idx--; //counterclockwise decrease pointer //------------------------------------------------------------------------------------------------------------ // when idx is from 0 to 5 select frequency digits //------------------------------------------------------------------------------------------------------------ if (idx >= 0 && idx < MAXDIGIT) { //if the current position is within the digits drawSymbol(0); //draw up arrow selectDigit(idx); //show cursor at current position and delete previous if (idx == 5) selectIcon(0, BLACK); //hide first icon selection } //------------------------------------------------------------------------------------------------------------ // when idx is from 6 to 8 select icons //------------------------------------------------------------------------------------------------------------ if (idx >= MAXDIGIT && idx <= MAXDIGIT + 2) { //if the current position is beyond the digits hideCursor(MAXDIGIT - 1); //hide cursor at last digit drawSymbol(1); //draw dn arrow selectIcon(idx - MAXDIGIT, WHITE); //select icon } } //----------------------------------------------------------------------------------------------------------------------------------- // submode SINGLEDIGIT: Encoder push event //----------------------------------------------------------------------------------------------------------------------------------- if (encoderPush) { encoderPush = false; //------------------------------------------------------------------------------------------------------------- // if a digit from 0 to 5 are selected go to mode DIGITCHANGE //------------------------------------------------------------------------------------------------------------- if (idx <= MAXDIGIT - 1) { hideCursor(idx); //flash cursor delay(250); //for selectDigit(idx); //visual confirmation drawSymbol(2); //draw turn icon mode = DIGITCHANGE; //change mode } //------------------------------------------------------------------------------------------------------------- // otherwise there is an icon selected then go to OPTIONS //------------------------------------------------------------------------------------------------------------- else { if (idx >= MAXDIGIT && idx <= MAXDIGIT + 2) { idy = idx - MAXDIGIT; selectOption(idy); idy = options[idy]; } } } break; //end mode SINGLEDIGIT case SWEEP://2 //---------------------------------------------------------------------------------------------------------------- // workmode SWEEP: Encoder rotation move cursor left and right for option selection //---------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idy < 2) idy++; if (encoderSpin == CCW && idy > 0) idy--; selectIcon(idy, WHITE); } if (encoderPush) { //----------------------------------------------------------------------------------------------------------------------------------- // workmode SWEEP: Encoder push go to OPTIONS, SWEEP OPTIONS or START/STOP sweep //----------------------------------------------------------------------------------------------------------------------------------- encoderPush = false; switch (idy) { case 0: lFreq = atol(Freq); selectOption(idy); idy = options[idy]; delay(100); if (_WorkMode != 2) displayFrequency(lLastFreq); SweepReset(); break; case 1: lFreq = atol(Freq); drawSymbol(9); drawSymbol(1); displaySweepIcons(); selectIcon(0, WHITE); idy = 0; displayFrequency(_Sweep(idy)); delay(100); SweepReset(); mode = OPTSWEEP; break; case 2: //** sweepStatus: STILL 0 (never started), 1 BREAK, 2 PAUSE ** if (sweepStatus == STILL || sweepStatus == PAUSE) { drawSymbol(3); //draw pause icon selectIcon(2, WHITE); //select icon FrequencySweep(); //run sweep } else { //if paused drawSymbol(4); //draw play icon sweepStatus = PAUSE; } break; } } if (sweepStatus == PAUSE) flashIcon(250); //flashing pause text break; //end mode SWEEP case OPTIONS://3 if (encoderLongPush) reset(); //----------------------------------------------------------------------------------------------------------------------------------- // mode OPTIONS: Encoder spin select option to change (workmode, wavetype, couplingmode) //----------------------------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idy < 2) idy++; if (encoderSpin == CCW && idy > 0) idy--; selectIcon(idy, WHITE); } //----------------------------------------------------------------------------------------------------------------------------------- // mode OPTIONS: Encoder push switch to relative mode //----------------------------------------------------------------------------------------------------------------------------------- if (encoderPush) { encoderPush = false; //selectIcon(idy, BLACK); selectOption(idy); hideCursor(0); idy = options[idy]; } break; //end mode OPTIONS case OPTMODE://4 //----------------------------------------------------------------------------------------------------------------------------------- // mode OPTMODE: Encoder spin select mode icons (logarithmic, singledigit, sweep) //----------------------------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idy < 2) idy++; if (encoderSpin == CCW && idy > 0) idy--; selectIcon(idy, WHITE); } //----------------------------------------------------------------------------------------------------------------------------------- // mode OPTMODE: Encoder push select workmode to set (stored in option[0]) //----------------------------------------------------------------------------------------------------------------------------------- if (encoderPush) { encoderPush = false; byte pMode = _WorkMode; switch (idy) { case 0: hideCursor(0); drawSymbol(0); lFreq = lLastFreq; displayFrequency(lFreq); _setWorkMode(LOGARITHMIC); break; case 1: drawSymbol(0); selectDigit(0); lFreq = lLastFreq; displayFrequency(lFreq); _setWorkMode(SINGLEDIGIT); break; case 2: lLastFreq = lFreq; displayFrequency(_SweepMin); //ready to start _setWorkMode(SWEEP); break; } mode = _WorkMode; if (pMode != _WorkMode) saveConfig(); if (_CouplingMode == OFF) resetCouplingMode(); idx = 0; drawAllIcons(); } break; //end mode OPTMODE case OPTWAVE://5 //---------------------------------------------------------------------------------------------------------------- // mode OPTWAVE: Encoder rotation move cursor left and right for wave selection (sqr, sin, tri) //---------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idy < 2) idy++; if (encoderSpin == CCW && idy > 0) idy--; selectIcon(idy, WHITE); } //-------------------------------------------------------------------------------------------------------------------- // mode OPTWAVE: Encoder push set new wave type //-------------------------------------------------------------------------------------------------------------------- if (encoderPush) { encoderPush = false; if (_WaveType != idy) { _setWaveType(idy); saveConfig(); } UpdateFrequency(); //updates wavetype drawAllIcons(); idx = 0; mode = _WorkMode; } break; //end mode OPTWAVE case OPTCOUP://6 //---------------------------------------------------------------------------------------------------------------- // mode OPTCOUP: Encoder rotation move cursor left and right for coupling mode selection //---------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idy < 2) idy++; if (encoderSpin == CCW && idy > 0) idy--; selectIcon(idy, WHITE); } //-------------------------------------------------------------------------------------------------------------------- // mode OPTCOUP: Encoder push select current coupling mode //-------------------------------------------------------------------------------------------------------------------- if (encoderPush) { encoderPush = false; setCouplingMode(idy); drawAllIcons(); idx = 0; mode = _WorkMode; } break; //end mode OPTCOUP case OPTSWEEP://7 //-------------------------------------------------------------------------------------------------------------------- // mode OPTSWEEP: Encoder spin select sweep values to edit //-------------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idy < 2) idy++; //clockwise increase pointer if (encoderSpin == CCW && idy > 0) idy--; //counterclockwise decrease pointer selectIcon(idy, WHITE); //select first icon displayFrequency(_Sweep(idy)); //display current sweep value } if (encoderPush) { encoderPush = false; //-------------------------------------------------------------------------------------------------------------------- // mode OPTSWEEP: Encoder push confirm sweep values to edit //-------------------------------------------------------------------------------------------------------------------- drawSymbol(0); selectDigit(0); selectIcon(idy, WHITE); idx = 0; displayFrequency(_Sweep(idy)); mode = SWEEPEDIT; } break; //end mode OPTSWEEP case SWEEPEDIT://8 //-------------------------------------------------------------------------------------------------------------- // mode SWEEPEDIT: Encoder spin select digit to change //-------------------------------------------------------------------------------------------------------------- if (encoderSpin) { if (encoderSpin == CW && idx < MAXDIGIT - 1) idx++; //clockwise increase pointer if (encoderSpin == CCW && idx > 0) idx--; //counterclockwise decrease pointer selectDigit(idx); } //-------------------------------------------------------------------------------------------------------------- // mode SWEEPEDIT: Encoder longpush exit from edit and return to SWEEP //-------------------------------------------------------------------------------------------------------------- if (encoderLongPush == LONGPUSH) { encoderPush = false; drawAllIcons(); displayFrequency(_SweepMin); hideCursor(idx); _setWorkMode(SWEEP); SweepReset(); mode = _WorkMode; delay(250); } if (encoderPush) { encoderPush = false; //------------------------------------------------------------------------------------------------------------- // mode SWEEPEDIT: Encoder push go to mode DIGITCHANGE //------------------------------------------------------------------------------------------------------------- hideCursor(idx); //flash cursor delay(250); //for selectDigit(idx); //visual confirmation drawSymbol(2); //draw turn icon mode = DIGITCHANGE; //change mode } break;//end mode SWEEPEDIT case DIGITCHANGE://9 //--------------------------------------------------------------------------------------------------------- // mode DIGITCHANGE: Encoder longpush exit from DIGITCHANGE when in SWEEP mode //--------------------------------------------------------------------------------------------------------- if (encoderLongPush == LONGPUSH && _WorkMode == SWEEP) { encoderPush = false; hideCursor(idx); drawSymbol(1); mode = OPTSWEEP; delay(250); } //--------------------------------------------------------------------------------------------------------- // mode DIGITCHANGE: Encoder rotation change digit value (0 -> 9 ->0 and so on) //--------------------------------------------------------------------------------------------------------- if (encoderSpin) { //encoder rotation if (encoderSpin == CW) { //clockwise direction Freq[idx]++; if (Freq[idx] > '9') Freq[idx] = '0'; } else { //counter clockwise direction Freq[idx]--; if (Freq[idx] < '0') Freq[idx] = '9'; } updateDigit(idx, Freq[idx]); //update digit on display } //--------------------------------------------------------------------------------------------------------- // mode DIGITCHANGE: Encoder push return to mode SINGLEDIGIT or SWEEPEDIT //--------------------------------------------------------------------------------------------------------- if (encoderPush) { //encoder push flag set by interrupt encoderPush = false; //reset event flag hideCursor(idx); //flash cursor delay(250); //for selectDigit(idx); //visual confirmation drawSymbol(0); if (_WorkMode == SWEEP) { long ltemp = _Sweep(idy) ; //save value _setSweep(idy, atol(Freq)); //convert new value from array to long if (_SweepMax > 0 && _SweepMax > _SweepMin && _SweepStep > 0) { //check congruency of the new sweep value if (_Sweep(idy) != ltemp) saveConfig(); //if value has changed write new value in EEPROM displayFrequency(_Sweep(idy)); mode = SWEEPEDIT; //change mode } else { _displayErrMsg; //display error message stored in flash mem delay(1000); _setSweep(idy, ltemp); //restore saved value displayFrequency(_Sweep(idy)); //redisplay value drawSymbol(2); //redraw turn icon } } else { //if not in sweep mode if (_CouplingMode == OFF) { //if coupling mode if OFF lLastFreq = atol(Freq); //save current frequency resetCouplingMode(); //set default coupling mode } UpdateFrequency(); //send frequency to DDS Module mode = SINGLEDIGIT; //change mode } } break; //end mode DIGITCHANGE default: break; } } //----------------------------------------------------------------------------------------------------------------------------------- // Push encoder event - Called by interrupt //----------------------------------------------------------------------------------------------------------------------------------- void encoderSwitch(void) { encoderPush = true; } //----------------------------------------------------------------------------------------------------------------------------------- // Utility functions //----------------------------------------------------------------------------------------------------------------------------------- // Draw graphics interface //---------------------------------------------------------------------------------------------------------------- void drawInterface() { display.clearDisplay(); display.display(); delay(1000); display.drawRoundRect(0, 0, 128, 64, 3, WHITE); //draw external frame display.fillRect(1, 1, 126, 14, WHITE); //draw caption frame displayText(12, 4, strFromFlash(0), BLACK, WHITE, SMALL); //print caption title delay(1000); if (cTime == 1) { //only on power on displayText(XPOS - 6, YPOS + 10, strFromFlash(1), WHITE, BLACK, BIG); //show Welcom message delay(1000); display.fillRect(2, 16, display.width() - 3, 35, BLACK); //clear Welcome message cTime = 0; } display.display(); displayText(XPOS + 84, YPOS + 4, strFromFlash(2), WHITE, BLACK, SMALL); //print "Hz" sprintf(Freq, "%06li", lFreq); //put frequency value into char array with template "000000" for (int i = MAXDIGIT - 1; i >= 0; i--) { display.drawChar(XPOS + 2 + i * DELTAX, YPOS, Freq[i] , WHITE, BLACK, BIG); //Display with animation effect from right to left display.display(); } }//end drawInterface() //---------------------------------------------------------------------------------------------------------------- // Print string in x,y pos with specified colors and size //---------------------------------------------------------------------------------------------------------------- void displayText(byte x, byte y, const char *str, byte foreColor, byte backColor, byte textSize) { display.setTextSize(textSize); //textsize: SMALL or BIG global const display.setTextColor(foreColor, backColor); //colors WHITE or BLACK global const of the library display.setCursor(x, y); //set the cursor position display.print(str); //str is the pointer to the string of chars display.display(); //update display } //---------------------------------------------------------------------------------------------------------------- // Copies element [i] of the string_table array from flash memory to the ram buffer and returns the pointer to the buffer //---------------------------------------------------------------------------------------------------------------- char* strFromFlash(byte i) { strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); return (char*)buffer; } //---------------------------------------------------------------------------------------------------------------- // Draw or clear a border around selected icon after clearing border of the previous one //---------------------------------------------------------------------------------------------------------------- void selectIcon(byte icon, byte color) { static byte prevIcon; display.drawRect(XPOS - 10 + prevIcon * 32, YPOS + 19, 29, 20, BLACK); display.drawRect(XPOS - 10 + icon * 32, YPOS + 19, 29, 20, color); display.display(); prevIcon = icon; } //---------------------------------------------------------------------------------------------------------------- // Display all workmode icons //---------------------------------------------------------------------------------------------------------------- void displayWorkModeIcons(void) { byte const *bitmap[3] = {imgLog, imgDigit, imgSweep}; _clearIconsArea; for (byte i = 0; i <= 2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display(); } //---------------------------------------------------------------------------------------------------------------- // Display all wavetype icons //---------------------------------------------------------------------------------------------------------------- void displayWaveTypeIcons(void) { byte const *bitmap[3] = {imgSqr, imgSin, imgTri}; _clearIconsArea; for (byte i = 0; i <= 2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display(); } //---------------------------------------------------------------------------------------------------------------- // Display all coupling mode icons //---------------------------------------------------------------------------------------------------------------- void displayCouplingModeIcons(void) { byte const *bitmap[3] = {imgCoAc, imgCoDc, imgCoOff}; _clearIconsArea; for (byte i = 0; i <= 2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display(); } //---------------------------------------------------------------------------------------------------------------- // Display all sweep icons //---------------------------------------------------------------------------------------------------------------- void displaySweepIcons(void) { byte const *bitmap[3] = {imgSwMax, imgSwMin, imgSwStep}; _clearIconsArea; for (byte i = 0; i <= 2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display(); } //---------------------------------------------------------------------------------------------------------------- // Draw all icons //---------------------------------------------------------------------------------------------------------------- void drawAllIcons(void) { _clearIconsArea; drawModeIcon(); if (_WorkMode == SWEEP || _WorkMode == SWEEPEDIT ) { display.drawBitmap(XPOS + 24, YPOS + 21, imgSwOpt, 25, 16, WHITE); display.drawBitmap(XPOS + 56, YPOS + 21, imgSwStart, 25, 16, WHITE); drawSymbol(1); idy = 2; selectIcon(idy, WHITE); //ready to sweep drawSmallWaveIcon(); drawSmallCouplingIcon(); } else { drawWaveIcon(); drawCouplingIcon(); drawSymbol(0); if (_WorkMode == SINGLEDIGIT) selectDigit(0); } display.display(); } //---------------------------------------------------------------------------------------------------------------- // Draws the icon based on the value of relative option //---------------------------------------------------------------------------------------------------------------- void drawModeIcon(void) { byte x = XPOS - 8, y = YPOS + 21; byte const *bitmap[3] = {imgLog, imgDigit, imgSweep}; display.fillRect(x, y, 25, 16, BLACK); display.drawBitmap(x, y, bitmap[_WorkMode], 25, 16, WHITE); display.display(); } void drawWaveIcon(void) { byte x = XPOS + 24, y = YPOS + 21; const byte *bitmap[3] = {imgSqr, imgSin, imgTri}; display.fillRect(x, y, 25, 16, BLACK); display.drawBitmap(x, y, bitmap[_WaveType], 25, 16, WHITE); display.display(); drawSmallWaveIcon(); } void drawCouplingIcon(void) { byte x = XPOS + 56, y = YPOS + 21; const byte *bitmap[3] = {imgCoAc, imgCoDc, imgCoOff}; display.fillRect(x, y, 25, 16, BLACK); display.drawBitmap(x, y, bitmap[_CouplingMode], 25, 16, WHITE); display.display(); drawSmallCouplingIcon(); } //---------------------------------------------------------------------------------------------------------------- // Draws small wave icon based on the value of relative option //---------------------------------------------------------------------------------------------------------------- void drawSmallWaveIcon(void) { byte x = 114, y = 41; const byte *bitmap[3] = {imgSqrSmall, imgSinSmall, imgTriSmall}; display.fillRect(x, y, 9, 8, BLACK); display.drawBitmap(x, y, bitmap[_WaveType], 9, 8, WHITE); display.display(); } //---------------------------------------------------------------------------------------------------------------- // Draws small coupling icon based on the value of relative option //---------------------------------------------------------------------------------------------------------------- void drawSmallCouplingIcon(void) { byte x = 114, y = 50; const byte *bitmap[3] = {imgAcSmall, imgDcSmall, imgOffSmall}; display.fillRect(x, y, 9, 8, BLACK); display.drawBitmap(x, y, bitmap[_CouplingMode], 9, 8, WHITE); display.display(); } //---------------------------------------------------------------------------------------------------------------- // Show cursor at x position //---------------------------------------------------------------------------------------------------------------- void showCursor(byte x) { display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, WHITE, WHITE, BIG); display.display(); } //---------------------------------------------------------------------------------------------------------------- // Hide cursor at x position //---------------------------------------------------------------------------------------------------------------- void hideCursor(byte x) { display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, BLACK, BLACK, BIG); display.display(); } //---------------------------------------------------------------------------------------------------------------- // Show cursor at x position after hiding previous one //---------------------------------------------------------------------------------------------------------------- void selectDigit(byte x) { static byte lastDigit; hideCursor(lastDigit); display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, WHITE, WHITE, BIG); display.display(); lastDigit = x; } //---------------------------------------------------------------------------------------------------------------- // Update single digit frequency to chr value //---------------------------------------------------------------------------------------------------------------- void updateDigit(byte digit, char chr) { display.drawChar(XPOS + 2 + digit * DELTAX, YPOS, chr , WHITE, BLACK, BIG); display.display(); } //---------------------------------------------------------------------------------------------------------------- // Drwaw or clear some symbols/icons //---------------------------------------------------------------------------------------------------------------- void drawSymbol(byte symbol) { switch (symbol) { case 0: //Top arrow display.fillRect(2, 20, 25, 16, BLACK); display.fillRect(2, 43, 14, 16, BLACK); display.drawChar(XPOS - 20 , YPOS + 4, ARROW, WHITE, BLACK, SMALL); //draw top arrow top break; case 1: //Bottom arrow display.fillRect(2, 20, 25, 16, BLACK); display.fillRect(2, 43, 14, 16, BLACK); display.drawChar(XPOS - 20 , YPOS + 25, ARROW, WHITE, BLACK, SMALL); //draw bottom arrow break; case 2: //Turn icon display.fillRect(2, 20, 25, 16, BLACK); display.drawBitmap(XPOS - 21, YPOS + 1, imgTurn, 13, 13, WHITE); //draw turn icon break; case 3: //Play icons display.fillRect(4, 23, 23, 11, BLACK); //clear pause icon display.drawBitmap(4, 23, imgSwRun, 23, 11, WHITE); //draw sweep icon display.fillRect(XPOS + 56, YPOS + 21, 25, 16, BLACK); //clear icon area display.drawBitmap(XPOS + 56, YPOS + 21, imgSwPause, 25, 16, WHITE); //drwaw sweep play symbol icon break; case 4: //Pause icons display.fillRect(4, 23, 23, 11, BLACK); //clear sweep icon display.drawBitmap(4, 23, imgSwPsd, 23, 11, WHITE); //draw pause icon display.fillRect(XPOS + 56, YPOS + 21, 25, 16, BLACK); //clear icon area display.drawBitmap(XPOS + 56, YPOS + 21, imgSwStart, 25, 16, WHITE); //draw sweep pause symbol icon break; case 9: //Simply clear symbol area display.fillRect(2, 20, 25, 16, BLACK); //clear top symbol area display.fillRect(2, 43, 14, 16, BLACK); //clear bottom symbol area break; default: break; } display.display(); } //--------------------------------------------------------------------------------------------------------------- // Set current frequency in DDS module, if frequency is 0 it will be set to 1 //--------------------------------------------------------------------------------------------------------------- void UpdateFrequency(void) { lFreq = atol(Freq); //convert char array to long if (lFreq < 1) { //the frequency at zero makes no sense ++Freq[MAXDIGIT - 1]; //increase the right most digit lFreq = 1; //set frequency to 1 } displayFrequency(lFreq); //update the display DDS_FrequencySet(lFreq, Wave[_WaveType]); //send the frequency value to DDS module lLastFreq = lFreq; //save current freq } //--------------------------------------------------------------------------------------------------------------- // Display the frequency with the six-zero template //--------------------------------------------------------------------------------------------------------------- void displayFrequency(long f) { sprintf(Freq, "%06li", f); //convert long to char with template '000000' displayText(XPOS + 2, YPOS, Freq , WHITE, BLACK, BIG); //print frequency on display display.display(); //refresh display } //--------------------------------------------------------------------------------------------------------------- // Reset coupling mode to default //--------------------------------------------------------------------------------------------------------------- void resetCouplingMode(void) { if (lFreq == 0 && _CouplingMode == OFF) { setCouplingMode(AC); drawCouplingIcon(); } } //--------------------------------------------------------------------------------------------------------------- // Set a specific coupling mode //--------------------------------------------------------------------------------------------------------------- void setCouplingMode(byte cMode) { byte pMode = _CouplingMode; switch (cMode) { case 0: if (lLastFreq > 0) lFreq = lLastFreq; digitalWrite(PinCoupling, LOW); _setCouplingMode(AC); break; case 1: if (lLastFreq > 0) lFreq = lLastFreq; digitalWrite(PinCoupling, HIGH); _setCouplingMode(DC); break; case 2: lLastFreq = lFreq; lFreq = 0; digitalWrite(PinCoupling, LOW); _setCouplingMode(OFF); break; } DDS_FrequencySet(lFreq, Wave[_WaveType]); displayFrequency(lFreq); if (cMode != pMode) saveConfig(); } //--------------------------------------------------------------------------------------------------------------- // Select options //--------------------------------------------------------------------------------------------------------------- void selectOption(byte opt) { selectIcon(opt, BLACK); switch (opt) { case 0: //workMode; displayWorkModeIcons(); selectIcon(_WorkMode, WHITE); mode = OPTMODE; break; case 1: //waveType; displayWaveTypeIcons(); selectIcon(_WaveType, WHITE); mode = OPTWAVE; break; case 2: //couplingMode; displayCouplingModeIcons(); selectIcon(_CouplingMode, WHITE); mode = OPTCOUP; break; } } //---------------------------------------------------------------------------------------------------------------- // Calculate logarithmic steps of the frequency //---------------------------------------------------------------------------------------------------------------- long AutoStep(long value, byte spin) { if (spin == CW) { if (value >= 100000) return 100000; if (value >= 10000) return 10000; if (value >= 1000) return 1000; if (value >= 100) return 100; if (value >= 10) return 10; if (value >= 1) return 1; return 0; // Invalid value } else { if (value <= 10) return 1; if (value <= 100) return 10; if (value <= 1000) return 100; if (value <= 10000) return 1000; if (value <= 100000) return 10000; if (value <= 1000000) return 100000; return 0; // Invalid value } } //------------------------------------------------------------------------------------------- // Start Sweep or restart it from where it came from before the pause //------------------------------------------------------------------------------------------- void FrequencySweep() { do { if (sweepDnPausedVal == 0) { //if sweepDown has not been stopped if (sweepUpPausedVal > 0) { //and sweepUp has been stopped sweepUpPausedVal = SweepUp(sweepUpPausedVal); //continues from current value } else { sweepUpPausedVal = SweepUp(_SweepMin); //else start from min } } if (sweepStatus != BREAK) { //if sweep has been stopped if (sweepDnPausedVal > 0) { //and sweepDn has been stopped sweepDnPausedVal = SweepDn(sweepDnPausedVal); //continues from current value } else { sweepDnPausedVal = SweepDn(_SweepMax); //else start from max } } } while (sweepStatus != BREAK); //continues sweep until stopped } //----------------------------------------------------------------------------------------- // Sweep Up from sweepmin push encoder to pause //----------------------------------------------------------------------------------------- long SweepUp(long sweepmin) { long f; for (f = sweepmin ; f < _SweepMax ; f += _SweepStep) { DDS_FrequencySet(f, Wave[_WaveType]); displayFrequency(f); if (encoderPush) { sweepStatus = BREAK; break; } } if (sweepStatus == BREAK) return f; return 0; } //----------------------------------------------------------------------------------------- // Sweep down from sweepmax push encoder to pause //----------------------------------------------------------------------------------------- long SweepDn(long sweepmax) { long f; for (f = sweepmax; f > _SweepMin ; f -= _SweepStep) { DDS_FrequencySet(f, Wave[_WaveType]); displayFrequency(f); if (encoderPush) { sweepStatus = BREAK; break; } } if (sweepStatus == BREAK)return f; return 0; } //----------------------------------------------------------------------------------------- // Clear global sweep vars and restore display //----------------------------------------------------------------------------------------- void SweepReset(void) { sweepStatus = STILL; sweepUpPausedVal = 0; sweepDnPausedVal = 0; display.fillRect(4, 23, 23, 11, BLACK); //clear sweep text display.display(); } //----------------------------------------------------------------------------------------- // Flash sweep pause icon //----------------------------------------------------------------------------------------- void flashIcon(int interval) { static long previousMillis; static boolean picShow; if (millis() - previousMillis >= interval) { previousMillis = millis(); picShow = !picShow; if (picShow) { display.drawBitmap(4, 23, imgSwPsd, 23, 11, WHITE); //drwaw sweep pause icon display.display(); } else { display.fillRect(4, 23, 23, 11, BLACK); //clear sweep pause icon display.display(); } } } //----------------------------------------------------------------------------------------- // Arduino software reset //----------------------------------------------------------------------------------------- void reset(void) { display.fillRect(1, 16, 125, 46, BLACK); display.display(); displayText(30, 30, strFromFlash(4), WHITE, BLACK, BIG); char str[2]; for (byte i = 3; i > 0; i--) { sprintf(str, "%d", i); displayText(95, 30, str, WHITE, BLACK, BIG); ...
ليست هناك تعليقات:
إرسال تعليق