原理簡單,附上原理圖
51hei截圖_20191113163908.png (482.79 KB, 下載次數: 68)
下載附件
2019-11-13 16:39 上傳
Arduino程序:
- #include "LedControl.h"
- #define A 0
- #define B 1
- #define C 2
- #define D 3
- #define E 4
- #define F 5
- #define G 6
- LedControl lc=LedControl(12,11,10,4); // lc is our object
- int numbers[40]={
- B00000000,B01111111,B01000001,B01111111,
- B00000000,B01111111,B00000000,B00000000,
- B00000000,B01111001,B01001001,B01001111,
- B00000000,B01111111,B01001001,B01001001,
- B00000000,B01111111,B00001000,B01111000,
- B00000000,B01111001,B01001001,B01001111,
- B00000000,B01001111,B01001001,B01111111,
- B00000000,B01111111,B01000000,B01000000,
- B00000000,B01111111,B01001001,B01111111,
- B00000000,B01111111,B01001001,B01111001};
- int characters[28]={
- B00000000,B00111111,B01001000,B00111111,
- B00000000,B00110110,B01001001,B01111111,
- B00000000,B00100010,B01000001,B00111110,
- B00000000,B00111110,B01000001,B01111111,
- B00000000,B01001001,B01001001,B01111111,
- B00000000,B01000000,B01001000,B01111111,
- B00000000,B00101110,B01001001,B00111110
- };
- int dig;
- int arr[5];
- int letter;
- int counter=0;
- int ref_freq;
- int ref_arr[5];
- int ref_dig;
- int bar;
- //clipping indicator variables
- boolean clipping = 0;
- //data storage variables
- byte newData = 0;
- byte prevData = 0;
- unsigned int time = 0;//keeps time and sends vales to store in timer[] occasionally
- int timer[10];//storage for timing of events
- int slope[10];//storage for slope of events
- unsigned int totalTimer;//used to calculate period
- unsigned int period;//storage for period of wave
- int index = 0;//current storage index
- float frequency;//storage for frequency calculations
- int maxSlope = 0;//used to calculate max slope as trigger point
- int newSlope;//storage for incoming slope data
- //variables for decided whether you have a match
- byte noMatch = 0;//counts how many non-matches you've received to reset variables if it's been too long
- byte slopeTol = 3;//slope tolerance- adjust this if you need
- int timerTol = 10;//timer tolerance- adjust this if you need
- //variables for amp detection
- unsigned int ampTimer = 0;
- byte maxAmp = 0;
- byte checkMaxAmp;
- byte ampThreshold = 30;//raise if you have a very noisy signal
- void setup(){
- lc.shutdown(0, false);
- lc.setIntensity(0, 8);
- lc.clearDisplay(0);
- lc.shutdown(1, false);
- lc.setIntensity(1, 8);
- lc.clearDisplay(1);
- lc.shutdown(2, false);
- lc.setIntensity(2, 8);
- lc.clearDisplay(2);
- lc.shutdown(3, false);
- lc.setIntensity(3, 8);
- lc.clearDisplay(3);
-
- Serial.begin(9600);
-
- pinMode(13,OUTPUT);//led indicator pin
- pinMode(12,OUTPUT);//output pin
-
- cli();//diable interrupts
-
- //set up continuous sampling of analog pin 0 at 38.5kHz
-
- //clear ADCSRA and ADCSRB registers
- ADCSRA = 0;
- ADCSRB = 0;
-
- ADMUX |= (1 << REFS0); //set reference voltage
- ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
-
- ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
- ADCSRA |= (1 << ADATE); //enabble auto trigger
- ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
- ADCSRA |= (1 << ADEN); //enable ADC
- ADCSRA |= (1 << ADSC); //start ADC measurements
- sei();//enable interrupts
- }
- ISR(ADC_vect) {
- //when new ADC value ready
-
- PORTB &= B11101111;//set pin 12 low
- prevData = newData;//store previous value
- newData = ADCH;//get value from A0
- if (prevData < 127 && newData >=127){//if increasing and crossing midpoint
- newSlope = newData - prevData;//calculate slope
- if (abs(newSlope-maxSlope)<slopeTol){//if slopes are ==
- //record new data and reset time
- slope[index] = newSlope;
- timer[index] = time;
- time = 0;
- if (index == 0){//new max slope just reset
- PORTB |= B00010000;//set pin 12 high
- noMatch = 0;
- index++;//increment index
- }
- else if (abs(timer[0]-timer[index])<timerTol && abs(slope[0]-newSlope)<slopeTol){//if timer duration and slopes match
- //sum timer values
- totalTimer = 0;
- for (byte i=0;i<index;i++){
- totalTimer+=timer[i];
- }
- period = totalTimer;//set period
- //reset new zero index values to compare with
- timer[0] = timer[index];
- slope[0] = slope[index];
- index = 1;//set index to 1
- PORTB |= B00010000;//set pin 12 high
- noMatch = 0;
- }
- else{//crossing midpoint but not match
- index++;//increment index
- if (index > 9){
- reset();
- }
- }
- }
- else if (newSlope>maxSlope){//if new slope is much larger than max slope
- maxSlope = newSlope;
- time = 0;//reset clock
- noMatch = 0;
- index = 0;//reset index
- }
- else{//slope not steep enough
- noMatch++;//increment no match counter
- if (noMatch>9){
- reset();
- }
- }
- }
-
- if (newData == 0 || newData == 1023){//if clipping
- clipping = 1;//currently clipping
- //Serial.println("clipping");
- }
-
- time++;//increment timer at rate of 38.5kHz
-
- ampTimer++;//increment amplitude timer
- if (abs(127-ADCH)>maxAmp){
- maxAmp = abs(127-ADCH);
- }
- if (ampTimer==1000){
- ampTimer = 0;
- checkMaxAmp = maxAmp;
- maxAmp = 0;
- }
-
- }
- void reset(){//clean out some variables
- index = 0;//reset index
- noMatch = 0;//reset match couner
- maxSlope = 0;//reset slope
- }
- void checkClipping(){//manage clipping indication
- if (clipping){//if currently clipping
- clipping = 0;
- }
- }
- void loop(){
-
- // checkClipping();
-
-
- if (checkMaxAmp>ampThreshold){
- frequency = 38462/float(period);//calculate frequency timer rate/period
-
- //print results
- if ((frequency>60) && (frequency<600))
- {
- Serial.println(frequency);
- //Serial.println(int (frequency));
- //|82|-96-|110|-128-|147|-171-|196|-221-|247|-288-|329|
- if (frequency<96) {letter = E; ref_freq=82;}
- else if (frequency<128) {letter = A; ref_freq=110;}
- else if (frequency<171) {letter = D; ref_freq=147;}
- else if (frequency<221) {letter = G; ref_freq= 196;}
- else if (frequency<288) {letter = B; ref_freq=247;}
- else {letter = E; ref_freq=329;}
- bar = ref_freq-frequency;
- counter++;
- if (counter==10)
- {
- counter=0;
- cli();// stop interruptions during the display printing
- //clear the displays
- lc.clearDisplay(0);
- lc.clearDisplay(1);
- lc.clearDisplay(2);
- lc.clearDisplay(3);
- //Print the Letter (A to G)
- lc.setColumn(3,0,characters[0+(4*letter)]);
- lc.setColumn(3,1,characters[1+(4*letter)]);
- lc.setColumn(3,2,characters[2+(4*letter)]);
- lc.setColumn(3,3,characters[3+(4*letter)]);
- //Print the tuner bar
- if (bar==0){
- lc.setColumn(0,0,0xFF); lc.setColumn(1,7,0xFF); // this is the bar
- lc.setRow(0,0,0xFF); lc.setRow(2,0,0xFF); //this is a square to accentuate the perfect tuning point
- lc.setRow(1,0,0xFF); lc.setRow(3,0,0xFF); //this is a square to accentuate the perfect tuning point
- lc.setColumn(0,7,0xFF); lc.setColumn(1,0,0xFF);}//this is a square to accentuate the perfect tuning point
- else if (bar==1) {lc.setColumn(0,1,0x7F); lc.setColumn(0,0,0x7F);}
- else if (bar==2) {lc.setColumn(0,2,0x7F); lc.setColumn(0,1,0x7F);}
- else if (bar==3) {lc.setColumn(0,3,0x7F); lc.setColumn(0,2,0x7F);}
- else if (bar==4) {lc.setColumn(0,4,0x7F); lc.setColumn(0,3,0x7F);}
- else if (bar==5) {lc.setColumn(0,5,0x7F); lc.setColumn(0,4,0x7F);}
- else if (bar==6) {lc.setColumn(0,6,0x7F); lc.setColumn(0,5,0x7F);}
- else if (bar==7) {lc.setColumn(0,7,0x7F); lc.setColumn(0,6,0x7F);}
- else if (bar==-1){lc.setColumn(1,7,0x7F); lc.setColumn(1,6,0x7F);}
- else if (bar==-2){lc.setColumn(1,6,0x7F); lc.setColumn(1,5,0x7F);}
- else if (bar==-3){lc.setColumn(1,5,0x7F); lc.setColumn(1,4,0x7F);}
- else if (bar==-4){lc.setColumn(1,4,0x7F); lc.setColumn(1,3,0x7F);}
- else if (bar==-5){lc.setColumn(1,3,0x7F); lc.setColumn(1,2,0x7F);}
- else if (bar==-6){lc.setColumn(1,2,0x7F); lc.setColumn(1,1,0x7F);}
- else if (bar==-7){lc.setColumn(1,1,0x7F); lc.setColumn(1,0,0x7F);}
- sei();//enable interrupts
- }
- }
- }
- }
- unsigned int count(unsigned int i) {
- unsigned int ret=1;
- while (i/=10) ret++;
- return ret;
- }
復制代碼 全部資料51hei下載地址:
tuner_standard.zip
(7.93 KB, 下載次數: 16)
2019-11-13 16:38 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|