标题:
arduino nuo实现吉他调音表的程序源码
[打印本页]
作者:
2312123
时间:
2019-11-13 16:39
标题:
arduino nuo实现吉他调音表的程序源码
原理简单,附上原理图
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
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1