/**************************************************************************///v.0.1 10.10.2018 Frequency generator 1.5k...200MHz . JrDrg//v.0.1c 10.14.2018 + OSC calibration//v.0.2c 10.15.2018 PLL clock Improvement + new Algorithm//v.0.3 10.16.2018 ch2 10MHz fix//v.0.3d 10.24.2018 Tuning、 bugFix//v.0.4 10.24.2018 +AD9833 WaveGen (DDS)1-1.2MHz Practical use:-800kHz//v.0.88 11.03.2018 High precision(8bits->16bits) temperature control//v.0.89 11.03.2018 Change WG Panel+Button,+ Step operation//v.0.91 11.05.2018 add Sirial cntrol//v.0.92 11.06.2018 freq High precision : float -> long//v.0.94 11.08.2018 キャリブレーション方法の変更//v.0.95 11.08.2018 si5351ライブラリの変更 PG:4k-225MHz/**************************************************************************/#include<Wire.h>#include<SPI.h>#include<LiquidCrystal.h>#include<avr/io.h>#include<avr/wdt.h>/* si5351.h - Si5351 library for Arduinohttps://github.com/etherkit/Si5351Arduino*/#include<si5351.h>Si5351si5351;//◆ Siral Debug 0:off 1:on 1<:manual checkbytedebug=0;intSGmenu=0;//0:Top 1:Pulse 2:Wave// select SW long Push > 5s => Top menuconstintloopwait=100;intchrcnt=0;//Sirial command I/F Chra countuint8_tinput[33];intcmdphase=0;//Sirial command phaselongNum;int64_tNumL;// heater setup#defineht_pin9// pin 3 -> 9(16bits PB1)// Temp ctrl start timeintinitwait=3000;// about 5minits [3000*loopwait]// Temp Transient characteristicsconstintinvtimerlimit_base=5000;// about 5s Temp ctrl intervalintinvtimerlimit=invtimerlimit_base;intinvtimer=0;inttemploop=0;intanlg1;intanlg2;//WaveGen OSC Tempfloattemp;floattemp2;floattemp2_old=0;floatdtemp;//◆ Target oven tempconstintterget_temp_base=52;//simple oven tempintterget_temp=terget_temp_base;intheater=160;//heater init set 150-205 <0-1023>/* Key setup */intlcd_key=0;intadc_key_in=0;intadc_key_in2=0;#definebtnRIGHT0#definebtnUP1#definebtnDOWN2#definebtnLEFT3#definebtnSELECT4#definebtnNONE5#definewaveSELECT6constintlcdLED=10;LiquidCrystallcd(8,3,4,5,6,7);//9->3/*AD9833 WaveGen (DDS) Setup*/constintSINE=0x2000;// Define AD9833's waveform register value.constintSQUARE=0x2028;// When we update the frequency, we need toconstintTRIANGLE=0x2002;// define the waveform when we end writing.intwave=0;intwaveType=SINE;//◆ Set wave generator initial frequency.unsignedlongfreq10=10000000;//freq * 10constlongfreqTRmax=1200000;// max 1.2MHz(Practical 1MHz)constlongfreqSQmax=1200000;// max 1.2MHz(Practical 500kHz)constlongfreqSImax=6000000;// max 5MHz(Practical 5MHz)unsignedlongfreqMAX=freqSImax;//◆ Wave generator OSC clockconstlongrefFreq_base=250003334;// On-board crystal reference frequency 25000318.4*10unsignedlongrefFreq10=refFreq_base;constintFSYNC=2;// Standard SPI pins for the AD9833 waveform generator. 10=>2constintCLK=13;// CLK and DATA pins are shared with the TFT display.constintDATA=11;constintCS=A3;//MCP41010 potentiometer 9=>A3(17)// digital pot values for differant wave forms to maintain constant output level(1-255)constintTRPOTmax=220;constintSQPOTmax=29;constintSIPOTmax=220;intTRPOT=126;intSQPOT=15;intSIPOT=126;intexPOTmax=SIPOTmax;intexPOT=SIPOT;// potmode for determining digipot settingbytepotVal=exPOT;intadc_key_wait=40;intread_LCD_buttons(){// take measures to chatteringadc_key_in=analogRead(0);delay(adc_key_wait);adc_key_in2=analogRead(0);if(abs(adc_key_in-adc_key_in2)>2)returnbtnNONE;// For V1.1 us this thresholdif(adc_key_in>1000)returnbtnNONE;// We make this the 1st option for speed reasons since it will be the most likely result// For V1.1 us this thresholdif(adc_key_in<50)returnbtnRIGHT;if(adc_key_in<250)returnbtnUP;if(adc_key_in<350)returnbtnDOWN;if(adc_key_in<550)returnbtnLEFT;if(adc_key_in<850)returnbtnSELECT;returnbtnNONE;}voidwait_btnNONE(){lcd_key=read_LCD_buttons();// read the buttonswhile(lcd_key!=btnNONE){lcd_key=read_LCD_buttons();// read the buttons}}//◆ Pulse Gen OSC Normal: oscf=25000000constlongoscf_base=25000000;//base OSC frequencyconstlongosc_devi_stnd=56990;// (偏差/10MHz) ppmlongpcal_devi=osc_devi_stnd;//Ref VoltfloatVref;//◆ Pulse Generator Initial Output Clock Frequint64_toutF=25000000;// initial frequency in HzconstlongoutF2=10000000;//ch2: Fix frequencyuint32_tstpx;//freq freq step sizeuint8_tchanged_f=1;charmsg10[10];chars8[8];/**************************************//* Calc Pram & Displays the frequency *//**************************************/voidcount_frequency(){/**************************************//* Displays the PG frequency *//**************************************/lcd.clear();lcd.setCursor(0,0);charmsg[12];chars[9];charmsg4[5];chars4[2];sprintf(msg,"PG %s",dtostrf((outF/10),8,0,s));sprintf(msg4,"%s Hz",dtostrf((outF%10),1,0,s4));lcd.print(msg);lcd.print(msg4);display_stpx();}/**************************************//* Display the frequency change step *//**************************************/voiddisplay_stpx(){lcd.setCursor(0,1);lcd.print("Stp:");switch(stpx){case10:lcd.print(" 10");break;case100:lcd.print(" 100");break;case1000:lcd.print(" 1k");break;case10000:lcd.print(" 10k");break;case100000:lcd.print("100k");break;case1000000:lcd.print(" 1M");break;case10000000:lcd.print(" 10M");break;}lcd.print("Hz ");}voidsetup_PGfreq0(){//◆ display setup paramif(changed_f>0){count_frequency();uint64_toutF_100=outF;outF_100=outF_100*100;si5351.output_enable(SI5351_CLK0,0);delay(10);si5351.set_correction(pcal_devi,SI5351_PLL_INPUT_XO);si5351.set_ms_source(SI5351_CLK0,SI5351_PLLA);si5351.set_freq(outF_100,SI5351_CLK0);si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_8MA);si5351.output_enable(SI5351_CLK0,1);si5351.update_status();}}voidsetup_PGfreq2(){uint64_toutF2_100=outF2;outF2_100=outF2_100*100;si5351.output_enable(SI5351_CLK2,0);delay(10);si5351.set_correction(pcal_devi,SI5351_PLL_INPUT_XO);si5351.set_ms_source(SI5351_CLK2,SI5351_PLLB);si5351.set_freq(outF2_100,SI5351_CLK2);si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_8MA);si5351.output_enable(SI5351_CLK2,1);si5351.update_status();}/**************************************//* Display the WG frequency *//**************************************/voiddisplay_WGfreq(){lcd.setCursor(0,0);charmsg[19];chars[13];// sprintf(msg, "WG %s Hz", dtostrf(freq, 9, 1, s));switch(waveType){caseSINE:{sprintf(msg,"Sin %s Hz",dtostrf((freq10/10.0),9,1,s));break;}caseTRIANGLE:{sprintf(msg,"Tri %s Hz",dtostrf((freq10/10.0),9,1,s));break;}caseSQUARE:{sprintf(msg,"Squ %s Hz",dtostrf((freq10/10.0),9,1,s));break;}}lcd.print(msg);}voiddisplay_WG(){lcd.clear();display_WGfreq();charmsg5[5];charss[4];lcd.setCursor(0,1);sprintf(msg5,"x%s ",dtostrf(exPOT,3,0,ss));lcd.print(msg5);lcd.setCursor(5,1);switch(stpx)//WG stpx=step*10{case1:lcd.print(" 0.1");break;case100:lcd.print("10Hz");break;case10000:lcd.print("1kHz");break;case1000000:lcd.print("100k");}}// AD9833 documentation advises a 'Reset' on first applying power.voidAD9833reset(){WriteRegister(0x100);// Write '1' to AD9833 Control register bit D8.delay(10);}// Set the frequency and waveform registers in the AD9833.voidAD9833setFrequency(unsignedlongfrequency10,intWaveform){unsignedlongFreqWord=((frequency10*pow(2,28))/refFreq10);intMSB=(int)((FreqWord&0xFFFC000)>>14);//Only lower 14 bits are used for dataintLSB=(int)(FreqWord&0x3FFF);//Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0LSB|=0x4000;MSB|=0x4000;WriteRegister(0x2100);WriteRegister(LSB);// Write lower 16 bits to AD9833 registersWriteRegister(MSB);// Write upper 16 bits to AD9833 registers.WriteRegister(0xC000);// Phase registerWriteRegister(Waveform);// Exit & Reset to SINE, SQUARE or TRIANGLE}voidWriteRegister(intdat){// Display and AD9833 use different SPI MODES so it has to be set for the AD9833 here.SPI.setDataMode(SPI_MODE2);digitalWrite(FSYNC,LOW);// Set FSYNC low before writing to AD9833 registersdelayMicroseconds(10);// Give AD9833 time to get ready to receive data.SPI.transfer(highByte(dat));// Each AD9833 register is 32 bits wide and each 16SPI.transfer(lowByte(dat));// bits has to be transferred as 2 x 8-bit bytes.digitalWrite(FSYNC,HIGH);//Write done. Set FSYNC high}voidMCP41010Write(bytevalue){// Note that the integer vale passed to this subroutine// is cast to a bytedigitalWrite(CS,LOW);delayMicroseconds(10);SPI.transfer(B00010001);// This tells the chip to set the potSPI.transfer(value);// This tells it the pot positiondelay(1);digitalWrite(CS,HIGH);}/* 電源電圧の読出 2014/7/19 ラジオペンチhttp://radiopench.blog96.fc2.com/*/floatcpuVcc(){// 電源電圧(AVCC)測定関数longsum=0;adcSetup(0x4E);// Vref=AVcc, input=internal1.1Vfor(intn=0;n<10;n++){sum=sum+adc();// adcの値を読んで積分}return(1.1*10240.0)/sum;// 電圧を計算して戻り値にする}voidadcSetup(bytedata){// ADコンバーターの設定ADMUX=data;// ADC Multiplexer Select Reg.ADCSRA|=(1<<ADEN);// ADC イネーブルADCSRA|=0x07;// AD変換クロック CK/128delay(10);// 安定するまで待つ}unsignedintadc(){// ADCの値を読むunsignedintdL,dH;ADCSRA|=(1<<ADSC);// AD変換開始while(ADCSRA&(1<<ADSC)){// 変換完了待ち}dL=ADCL;// LSB側読み出しdH=ADCH;// MSB側returndL|(dH<<8);// 10ビットに合成した値を返す}// Array to Numeric conversionint64_tcovNum(){// 入力値の10倍を返す。小数点以下は1桁以内限定uint8_tasc;uint32_tascN;int64_tNumL=0;for(int8_ti=0;i<chrcnt;i++){asc=input[i];if((asc!='.')&&(asc!='-')&&(asc!=' ')){if((asc>=0x30)&&(asc<0x3A)){ascN=(uint32_t)(asc-0x30);NumL=(uint32_t)(NumL*10ULL);NumL=(uint32_t)(NumL+ascN);}elseNumL=0;}}if(input[chrcnt-2]!='.')NumL=(uint32_t)(NumL*10UL);if(input[0]=='-')NumL=-1*NumL;return(int64_t)NumL;}// Software resetvoidsoftware_reset(){wdt_disable();wdt_enable(WDTO_15MS);while(1){}}voidsetup(void){lcd.begin(16,2);// PGWire.begin();// WG AD9833SPI.begin();Serial.begin(115200);delay(1000);Serial.println("******************");Serial.println("* 1-1.2MHz WG *");Serial.println("* 4k-220MHz PG *");Serial.println("******************");Serial.println("hello");if(debug){Serial.print("* Debug mode :");Serial.print(debug);Serial.println(" *");Serial.print("* SGmenu :");Serial.print(SGmenu);Serial.println(" *");Serial.println("");}/* 電源電圧の読出 2014/7/19 ラジオペンチhttp://radiopench.blog96.fc2.com/ */Vref=cpuVcc();// 電源電圧測定// Heater pinpinMode(ht_pin,OUTPUT);//10bit高速PWMTCCR1A=0b10000011;TCCR1B=0b00001001;OCR1A=(unsignedint)(1023*(heater/1023.0));// PORTB = 0b00000010; //pul uppinMode(lcdLED,OUTPUT);// Startting Tittlelcd.setCursor(0,0);// lcd.print("* WG: 0.1-1.2MHz*");lcd.print("WG-1.2M//PG-200M");lcd.setCursor(0,1);// lcd.print("* PG: 4k-225MHz *");lcd.print("18.1189 by JrDrg");// pulse gen setup init clock// initialize the Si5351booli2c_found;i2c_found=si5351.init(SI5351_CRYSTAL_LOAD_10PF,0,0);if(!i2c_found){lcd.setCursor(0,1);lcd.print(" PG clockgen error");while(1);}si5351.reset();delay(500);si5351.init(SI5351_CRYSTAL_LOAD_10PF,0,0);/* set_correction(int32_t corr, enum si5351_pll_input ref_osc) corr - Correction factor in ppb ref_osc - Desired reference oscillator (use the si5351_pll_input enum) ref_osc - Desired reference oscillator 0: crystal oscillator (XO) 1: external clock input (CLKIN) */changed_f=1;/* Enable the clocks & Set Freq */setup_PGfreq0();setup_PGfreq2();// Wave generator StartuppinMode(CS,OUTPUT);pinMode(FSYNC,OUTPUT);AD9833reset();// Reset AD9833 module after power-up.delay(500);AD9833setFrequency(freq10,waveType);// Set the frequency and wave typedelay(5);MCP41010Write(potVal);//Set Potentionmeterif(debug){Serial.print(" potVal :");Serial.println(potVal);}// temp dummy readanlg1=analogRead(1);anlg2=analogRead(2);delay(3000);//3secondsanlg2=0;for(inti=1;i<=20;i++){anlg2=anlg2+analogRead(2);delay(5);}anlg2=anlg2/20;temp2_old=((Vref*anlg2)/1024/2.907)*100-60;}voidloop(void){switch(SGmenu){case0:{//★★ Top Menu// SGmenu = 1;//0:Top 1:Pulse 2:Wave// select SW long Push > 5s => Top menu// lcd.clear();lcd.setCursor(0,0);charmsg[19];chars[13];switch(waveType){caseSINE:{sprintf(msg,"SI %s ",dtostrf(freq10/10.0,9,1,s));break;}caseTRIANGLE:{sprintf(msg,"TR %s ",dtostrf(freq10/10.0,9,1,s));break;}caseSQUARE:{sprintf(msg,"SQ %s ",dtostrf(freq10/10.0,9,1,s));break;}}lcd.print(msg);lcd.setCursor(0,1);charmsg4[5];chars4[2];sprintf(msg,"PG %s",dtostrf((outF/10),8,0,s));sprintf(msg4,"%s Hz",dtostrf((outF%10),1,0,s4));lcd.print(msg);lcd.print(msg4);// sprintf(msg, "PG %s Hz", dtostrf(outF, 9, 0, s));// lcd.print(msg);lcd_key=read_LCD_buttons();// read the buttonsswitch(lcd_key)// depending on which button was pushed, we perform an action{casebtnUP:{SGmenu=2;lcd.setCursor(0,1);changed_f=1;stpx=1;lcd.print(" ");lcd.setCursor(14,0);lcd.print("Hz");wait_btnNONE();break;}casebtnDOWN:{SGmenu=1;stpx=10;lcd.setCursor(0,0);lcd.print(" ");changed_f=1;wait_btnNONE();break;}}}case1:{//★★ PULSE GENERATER/**************************************//* Change the frequency *//* btnUP Increment *//* btnDOWN Decrement *//* btnRIGHT Increment Tweak *//* btnLEFT Decrement Tweak *//**************************************/lcd_key=read_LCD_buttons();// read the buttonsswitch(lcd_key)// depending on which button was pushed, we perform an action{casebtnUP:{outF+=stpx;changed_f=1;break;}casebtnDOWN:{outF-=stpx;changed_f=1;break;}casebtnRIGHT:{outF+=1;changed_f=1;break;}casebtnLEFT:{outF-=1;changed_f=1;break;}}// btnSELECT frequency step Rengeif(lcd_key==btnSELECT)// check long push (Return SGmenu){digitalWrite(lcdLED,HIGH);// check btnSELECT > 5sfor(inti=1;i<=int(2500/adc_key_wait);i++){lcd_key=read_LCD_buttons();// read the buttonsif(lcd_key!=btnSELECT)break;delay(adc_key_wait);}if(lcd_key!=btnSELECT)lcd_key=btnSELECT;elseSGmenu=0;}if(SGmenu!=1)break;if(lcd_key==btnSELECT){switch(stpx){case10:stpx=100;break;case100:stpx=1000;break;case1000:stpx=10000;break;case10000:stpx=100000;break;case100000:stpx=1000000;break;case1000000:stpx=10000000;break;case10000000:stpx=10;break;}display_stpx();}if((changed_f>0)&&!(debug>1)){// check over rengeif(outF>225000000)outF=4000;if(outF<4000)outF=225000000;if(outF<0)outF=225000000;setup_PGfreq0();changed_f=0;}break;}case2:{//★★ Wave Generator/*************************************//* Change the frequency & potention *//* btnUP freq Increment *//* btnDOWN freq Decrement *//* btnRIGHT pot Increment *//* btnLEFT pot Decrement *//* btnSELECT Change Wave *//*************************************/lcd_key=read_LCD_buttons();// read the buttonswhile((lcd_key==btnUP)||(lcd_key==btnDOWN)){switch(lcd_key)// depending on which button was pushed, we perform an action{casebtnUP:{freq10+=stpx;break;}casebtnDOWN:{freq10-=stpx;break;}}changed_f=1;// check over rengeif(freq10>freqMAX)freq10=1;elseif(freq10<=0)freq10=freqMAX*10;// if (freq > 1000000) freq = long(freq / 10) * 10;AD9833setFrequency(freq10,waveType);// Set the frequency and wave typedisplay_WGfreq();changed_f=0;delay(adc_key_wait);lcd_key=read_LCD_buttons();// read the buttons}switch(lcd_key)// depending on which button was pushed, we perform an action{casebtnRIGHT:{exPOT+=1;changed_f=1;break;}casebtnLEFT:{exPOT-=1;changed_f=1;break;}}// check over rengeif(changed_f>0){if(freq10>freqMAX*10)freq10=1;elseif(freq10<=0)freq10=freqMAX*10;if(exPOT>exPOTmax)exPOT=0;elseif(exPOT<0)exPOT=exPOTmax;potVal=exPOT;MCP41010Write(potVal);//Set Potentionmeterdisplay_WG();changed_f=0;}// btnSELECT WaveTypeif(lcd_key==btnSELECT)// check long push (Return SGmenu){uint32_tt_cont;digitalWrite(lcdLED,HIGH);// check btnSELECT > 5sfor(t_cont=1;t_cont<=int(2500/adc_key_wait);t_cont++){lcd_key=read_LCD_buttons();// read the buttonsif(lcd_key!=btnSELECT)break;if(t_cont>int(2500/adc_key_wait/2)){lcd.setCursor(0,0);lcd.print("***");}delay(adc_key_wait);}if(debug){Serial.println(t_cont);}if(lcd_key!=btnSELECT){if(t_cont>int(2500/adc_key_wait/2))lcd_key=waveSELECT;elselcd_key=btnSELECT;}else{SGmenu=0;break;}if(SGmenu!=0){if(lcd_key==btnSELECT){changed_f=1;switch(stpx){case1:stpx=100;break;case100:stpx=10000;break;case10000:stpx=1000000;break;case1000000:stpx=1;}}if((lcd_key==waveSELECT)&&(freq10<=freqSQmax*10)){//freqSQmax >> other maxchanged_f=1;switch(waveType){caseSINE:{SIPOT=exPOT;waveType=TRIANGLE;freqMAX=freqTRmax;exPOTmax=TRPOTmax;exPOT=TRPOT;break;}caseTRIANGLE:{TRPOT=exPOT;waveType=SQUARE;freqMAX=freqSQmax;exPOTmax=SQPOTmax;exPOT=SQPOT;break;}caseSQUARE:{SQPOT=exPOT;waveType=SINE;freqMAX=freqSImax;exPOTmax=SIPOTmax;exPOT=SIPOT;break;}}AD9833setFrequency(freq10,waveType);// Set the frequency and wave type}}}if(SGmenu!=2)break;if(changed_f){display_WG();changed_f=0;}break;}}/* heater control */// get PG OSC tempanlg1=0;for(inti=1;i<=20;i++){anlg1=anlg1+analogRead(1);delay(5);}anlg1=anlg1/20;temp=((Vref*anlg1)/1024)*100-60;// get WG OSC temp2anlg2=0;for(inti=1;i<=20;i++){anlg2=anlg2+analogRead(2);delay(5);}anlg2=anlg2/20;temp2=((Vref*anlg2)/1024/2.907)*100-60;// OpAmp gain: x2.907if(abs(terget_temp-temp2)<1)initwait=0;// 設定温度に近い場合、温度制御を強制スタートif(initwait>0)initwait-=1;// Temp ctrl start waitingelse{if((terget_temp-temp2)<-0.8)invtimerlimit=invtimerlimit_base/4;elseinvtimerlimit=invtimerlimit_base;if((invtimer*loopwait)>invtimerlimit){invtimer=0;if(abs(terget_temp-temp2)<=0.4)heater+=0;elseif(((terget_temp-temp2)>4)&&(heater<984)&&(temp2<=temp2_old)){heater+=40;temploop=0;}elseif(((terget_temp-temp2)<-3)&&(heater>19)&&(temp2>=temp2_old)){heater-=20;temploop=0;}elseif(abs(temp2-temp2_old)<=0.4){heater+=0;temploop+=1;if(temploop>5){temploop=0;if((terget_temp-temp2)>0)heater+=1;else{if((terget_temp-temp2)<=2)heater-=1;elseheater-=2;}}}elseif(((terget_temp-temp2)>0)&&(heater<1023)&&(temp2<=temp2_old)){heater=heater+=1;temploop=0;}elseif(((terget_temp-temp2)<0)&&(heater>0)&&(temp2>=temp2_old)){heater-=1;temploop=0;}temp2_old=temp2;// set heater PWM Duty(heater/1023.0)OCR1A=(unsignedint)(1023*(heater/1023.0));}invtimer+=1;}if(debug){Serial.print("** ");Serial.print(Vref);Serial.print("V ");Serial.print(initwait);Serial.print(" ");Serial.print(invtimer);Serial.print(" ");Serial.print(temploop);Serial.print(" ");Serial.print(heater);Serial.print(" ");Serial.print(temp2_old);Serial.print("℃ ");Serial.print(temp2);Serial.print("℃ ");Serial.print(temp);Serial.println("℃ ");}/* 温度が設定値に近づくとバックライトが点灯 温度が異常だとバックライトが点滅 温度がほぼ設定値になるまで、温度差を点滅表示 */dtemp=temp2-terget_temp;if(abs(dtemp)<0.8)digitalWrite(lcdLED,HIGH);else{if(dtemp<5){if((initwait%2)>0){digitalWrite(lcdLED,LOW);}else{digitalWrite(lcdLED,HIGH);}}else{// set heater PWM Duty 0% = Power downOCR1A=(unsignedint)(1023*(0/1023.0));digitalWrite(lcdLED,LOW);}}if(SGmenu>0){temp=(temp2+temp)/2;charmsgT[5];charsT[5];lcd.setCursor(11,1);if(initwait>0){if((initwait%2)>0){lcd.print(" ");}else{sprintf(msgT," %s0",dtostrf(dtemp,2,2,sT));lcd.print(msgT);}}else{if(((invtimer%2)>0)&&(abs(dtemp)>0.4)){lcd.print(" ");}else{sprintf(msgT,"%s",dtostrf(int(heater/1023.0*100.0),3,0,sT));lcd.print(msgT);lcd.print('%');}}}//Sirial command I/F chrcnt/* cmdphase 1:w(WG) 5:<freq:0.1-1200000.0> 6:<POT:0-127> 7:i(sin) :r(tri) :q(squ) 2:p(PG) 10:<freq:1-205000000> 3:t(temp) 11:<Target_temp:40-55> 12:<heater:0-1023> 4:g(get) return status PG freq,WG freq,WG waveform,WG pot,temp2,temp,heater,target temp 13:c(WG calibration) 16:<+-freq/10:-500~+500> 14:C(PG calibration) 17:<+-freq/10:-500~+500> 18:r(reboot) 19:D(set Direct PG parameter) ....opt. 20:d(Dump Direct PG parameter) 21:h(hello) for Sirial Command Sync 0:No command [\]:end mark */if(Serial.available()){input[chrcnt]=Serial.read();if(chrcnt>32||input[chrcnt]=='\\'){// chrcnt=chrcnt-1; // ignore last'Y'switch(cmdphase){case0:{switch(input[0]){case'h':{Serial.println("Hi! my Master (^^) ");cmdphase=0;break;}case'w':{Serial.println("WG");cmdphase=5;break;}case'p':{Serial.println("PG");cmdphase=10;break;}case't':{Serial.println("TEMP");cmdphase=11;break;}case'g':{Serial.print("Status: ");Serial.print((uint32_t)outF);Serial.print(" ");Serial.print(freq10/10,DEC);Serial.print(".");Serial.print((freq10%10),DEC);Serial.print(" ");Serial.print(waveType);Serial.print(" ");Serial.print(exPOT);Serial.print(" ");Serial.print(temp2,1);Serial.print(" ");Serial.print(temp,1);Serial.print(" ");Serial.print(heater);Serial.print(" ");Serial.println(terget_temp,1);//Serial.print(" ");//Serial.print(refFreq10 / 10, DEC); Serial.print("."); Serial.print((refFreq10 % 10), DEC);//Serial.print(" ");//Serial.println( pcal_devi );cmdphase=0;break;}case'c':{Serial.println("WG");cmdphase=16;break;}case'C':{Serial.println("PG");cmdphase=17;break;}case'r':{Serial.println("Rboot");software_reset();cmdphase=0;break;}case'D':{Serial.println("OPT");cmdphase=0;//19break;}case'd':{Serial.print("PG: ");si5351.update_status();Serial.print("SYS_INIT: ");Serial.print(si5351.dev_status.SYS_INIT);Serial.print(" LOL_A: ");Serial.print(si5351.dev_status.LOL_A);Serial.print(" LOL_B: ");Serial.print(si5351.dev_status.LOL_B);Serial.print(" LOS: ");Serial.print(si5351.dev_status.LOS);Serial.print(" REVID: ");Serial.println(si5351.dev_status.REVID);cmdphase=0;break;}default:{Serial.println("What? ");cmdphase=0;break;}}break;}case5:{Num=covNum();Serial.println("WG2");//Serial.print(Num / 10, DEC); Serial.print("."); Serial.println((Num % 10), DEC);if((Num>0)&&(Num<120000001)){freq10=Num;cmdphase=6;changed_f=0;}else{cmdphase=0;}break;}case6:{Num=covNum();//Serial.print(Num / 10, DEC);Serial.println("WG3");if((Num>=0)&&(Num<2550)){exPOT=Num/10;//Serial.println(exPOT);switch(waveType){caseSINE:{SIPOT=exPOT;break;}caseTRIANGLE:{TRPOT=exPOT;break;}caseSQUARE:{SQPOT=exPOT;break;}}}changed_f=0;cmdphase=7;break;}case7:{Serial.println("WG4");switch(input[0]){case'i':{waveType=SINE;changed_f=1;break;}case'r':{waveType=TRIANGLE;changed_f=1;break;}case'q':{waveType=SQUARE;changed_f=1;break;}default:{changed_f=0;break;}}if(changed_f=1){switch(waveType){caseTRIANGLE:{freqMAX=freqTRmax;exPOTmax=TRPOTmax;break;}caseSQUARE:{freqMAX=freqSQmax;exPOTmax=SQPOTmax;break;}caseSINE:{freqMAX=freqSImax;exPOTmax=SIPOTmax;break;}}AD9833setFrequency(freq10,waveType);// Set the frequency and wave typepotVal=exPOT;//Serial.println(exPOT);MCP41010Write(potVal);//Set Potentionmeterdisplay_WG();changed_f=0;cmdphase=0;}break;}case10:{NumL=(int64_t)covNum();if((NumL>=40000)&&(NumL<=2250000000)){outF=(int64_t)(NumL/10);//Serial.print((uint32_t)outF);Serial.println("PG");changed_f=1;setup_PGfreq0();changed_f=0;}cmdphase=0;break;}case11:{Num=covNum();if((Num>399)&&(Num<551)){//Serial.print(Num / 10, DEC);Serial.println("TG");terget_temp=Num/10;cmdphase=12;}else{cmdphase=0;}break;}case12:{Num=covNum();if((Num>=0)&&(Num<10231)){//Serial.print(Num / 10, DEC);Serial.println("HT");heater=Num/10;OCR1A=(unsignedint)(1023*(heater/1023.0));}cmdphase=0;break;}case16:{Num=covNum();if((Num>-2000001)&&(Num<2000001)){Serial.println("WG");//Serial.print(Num / 10, DEC); Serial.print("."); Serial.println(abs(Num % 10), DEC);refFreq10=refFreq_base+Num;changed_f=1;AD9833setFrequency(freq10,waveType);// Set the frequency and wave typedisplay_WG();changed_f=0;}cmdphase=0;break;}case17:{Num=covNum();if((Num>-2000001)&&(Num<2000001)){Serial.println("PG");//Serial.print(Num / 10, DEC); Serial.print("."); Serial.println(abs(Num % 10), DEC);// クロック偏差をppmで入力。100MHzを偏差0.1まで計測、差分を設定pcal_devi=Num;changed_f=1;setup_PGfreq0();setup_PGfreq2();changed_f=0;}cmdphase=0;break;}default:{}cmdphase=0;break;}chrcnt=0;}else{chrcnt++;}}//loop delaydelay(loopwait);}// END
シリアルからのコマンドでも操作できるように作っていますので、WindowsからGUIで制御できるツールもついでに作成しちゃいました。
言語は、python
開発環境は、Visual Studio Code
pythonは、本来は本格的なWeb用のプログラムなどを作成するものと思いますが、昔のBASIC的な位置付けでお手軽なプログラム言語としても使えます。
最近のPCはパワーが余っていますから、高速処理が苦手なインタプリタですが、中間言語で実行するのもあり、そこそこリアルタイムな処理も可能です。
また、マルチプラットホーム対応なのもGood、必要に応じて実行形式も作成可能です。
import wx
import time
import os
import serial
#from serial.tools import list_ports
import argparse
# シリアル設定,本来は引数か、自動検出等があれば汎用的だが、現状専用機仕様なので…
comport = ‘COM5’
combps = 115200
# OSCキャリブレーション値
# このキャリブレーション値と後出のHeater値は起動時に自動設定が良いかもしれない。
pgcal_d = 5683.0 # by GPS
wgcal_d = 3334
pgcal = pgcal_d
wgcal = wgcal_d
# ボードからの戻り値変換用
SINE = 0x2000
SQUARE = 0x2028
TRIANGLE = 0x2002
# 変数の宣言と、てきとうな初期設定
wgwavetype = 0
pg_freq = 25000000
pgfreq = pg_freq
wg_freq = 1200000
wgfreq=wg_freq
wg_type = ‘SINE’
wg_potn = 105
wgpot = wg_potn
# 変数宣言と、将来Target温度・Heaterの設定機能追加時の為。現状値はダミー
wg_temp = 52.5
pg_temp = 47.2
tg_temp = 52.0
osc_heater = 194
# 温度異常時にカラー表示を変えたい為、現時点機能なし
over_temp = tg_temp + 4
wg_temp_color = ‘#ff99b3’
# ボードに起動時(reset含む)おーぷにおんぐメッセージを読み飛ばすフラグ
hello_flag = 0
# wavetypeのシリアルコマンド、数字->1文字コマンドへ変換用文字列
wave_irq = ‘irq’
# シリアルのセマフォフラグ
ser_busy = 0
class MainFrame(wx.Frame):
#トップレベルウィンドウクラス
def __init__(self):
super().__init__(None, wx.ID_ANY, ‘WG/PC Control Panel’,style=(wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX))
コメントを残す