EDABOSS电子论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 569|回复: 0

[资料共享] arduino nuo实现吉他调音表的程序源码

[复制链接]

5

主题

0

回帖

26

E币

技术员

Rank: 2

积分
10
发表于 2019-12-4 17:25:35 | 显示全部楼层 |阅读模式
原理简单,附上原理图

1.png
Arduino程序:


  1. #include "LedControl.h"

  2. #define A 0
  3. #define B 1
  4. #define C 2
  5. #define D 3
  6. #define E 4
  7. #define F 5
  8. #define G 6


  9. LedControl lc=LedControl(12,11,10,4); // lc is our object

  10. int numbers[40]={
  11. B00000000,B01111111,B01000001,B01111111,
  12. B00000000,B01111111,B00000000,B00000000,
  13. B00000000,B01111001,B01001001,B01001111,
  14. B00000000,B01111111,B01001001,B01001001,
  15. B00000000,B01111111,B00001000,B01111000,
  16. B00000000,B01111001,B01001001,B01001111,
  17. B00000000,B01001111,B01001001,B01111111,
  18. B00000000,B01111111,B01000000,B01000000,
  19. B00000000,B01111111,B01001001,B01111111,
  20. B00000000,B01111111,B01001001,B01111001};

  21. int characters[28]={
  22. B00000000,B00111111,B01001000,B00111111,
  23. B00000000,B00110110,B01001001,B01111111,
  24. B00000000,B00100010,B01000001,B00111110,
  25. B00000000,B00111110,B01000001,B01111111,
  26. B00000000,B01001001,B01001001,B01111111,
  27. B00000000,B01000000,B01001000,B01111111,
  28. B00000000,B00101110,B01001001,B00111110
  29. };


  30. int dig;
  31. int arr[5];
  32. int letter;
  33. int counter=0;
  34. int ref_freq;
  35. int ref_arr[5];
  36. int ref_dig;
  37. int bar;


  38. //clipping indicator variables
  39. boolean clipping = 0;

  40. //data storage variables
  41. byte newData = 0;
  42. byte prevData = 0;
  43. unsigned int time = 0;//keeps time and sends vales to store in timer[] occasionally
  44. int timer[10];//storage for timing of events
  45. int slope[10];//storage for slope of events
  46. unsigned int totalTimer;//used to calculate period
  47. unsigned int period;//storage for period of wave
  48. int index = 0;//current storage index
  49. float frequency;//storage for frequency calculations
  50. int maxSlope = 0;//used to calculate max slope as trigger point
  51. int newSlope;//storage for incoming slope data

  52. //variables for decided whether you have a match
  53. byte noMatch = 0;//counts how many non-matches you've received to reset variables if it's been too long
  54. byte slopeTol = 3;//slope tolerance- adjust this if you need
  55. int timerTol = 10;//timer tolerance- adjust this if you need

  56. //variables for amp detection
  57. unsigned int ampTimer = 0;
  58. byte maxAmp = 0;
  59. byte checkMaxAmp;
  60. byte ampThreshold = 30;//raise if you have a very noisy signal

  61. void setup(){

  62.   lc.shutdown(0, false);
  63.   lc.setIntensity(0, 8);
  64.   lc.clearDisplay(0);

  65.   lc.shutdown(1, false);
  66.   lc.setIntensity(1, 8);
  67.   lc.clearDisplay(1);

  68.   lc.shutdown(2, false);
  69.   lc.setIntensity(2, 8);
  70.   lc.clearDisplay(2);

  71.   lc.shutdown(3, false);
  72.   lc.setIntensity(3, 8);
  73.   lc.clearDisplay(3);
  74.   
  75.   Serial.begin(9600);
  76.   
  77.   pinMode(13,OUTPUT);//led indicator pin
  78.   pinMode(12,OUTPUT);//output pin
  79.   
  80.   cli();//diable interrupts
  81.   
  82.   //set up continuous sampling of analog pin 0 at 38.5kHz

  83.   //clear ADCSRA and ADCSRB registers
  84.   ADCSRA = 0;
  85.   ADCSRB = 0;
  86.   
  87.   ADMUX |= (1 << REFS0); //set reference voltage
  88.   ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
  89.   
  90.   ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
  91.   ADCSRA |= (1 << ADATE); //enabble auto trigger
  92.   ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
  93.   ADCSRA |= (1 << ADEN); //enable ADC
  94.   ADCSRA |= (1 << ADSC); //start ADC measurements

  95.   sei();//enable interrupts
  96. }

  97. ISR(ADC_vect) {
  98.   //when new ADC value ready
  99.   
  100.   PORTB &= B11101111;//set pin 12 low
  101.   prevData = newData;//store previous value
  102.   newData = ADCH;//get value from A0
  103.   if (prevData < 127 && newData >=127){//if increasing and crossing midpoint
  104.     newSlope = newData - prevData;//calculate slope
  105.     if (abs(newSlope-maxSlope)<slopeTol){//if slopes are ==
  106.       //record new data and reset time
  107.       slope[index] = newSlope;
  108.       timer[index] = time;
  109.       time = 0;
  110.       if (index == 0){//new max slope just reset
  111.         PORTB |= B00010000;//set pin 12 high
  112.         noMatch = 0;
  113.         index++;//increment index
  114.       }
  115.       else if (abs(timer[0]-timer[index])<timerTol && abs(slope[0]-newSlope)<slopeTol){//if timer duration and slopes match
  116.         //sum timer values
  117.         totalTimer = 0;
  118.         for (byte i=0;i<index;i++){
  119.           totalTimer+=timer[i];
  120.         }
  121.         period = totalTimer;//set period
  122.         //reset new zero index values to compare with
  123.         timer[0] = timer[index];
  124.         slope[0] = slope[index];
  125.         index = 1;//set index to 1
  126.         PORTB |= B00010000;//set pin 12 high
  127.         noMatch = 0;
  128.       }
  129.       else{//crossing midpoint but not match
  130.         index++;//increment index
  131.         if (index > 9){
  132.           reset();
  133.         }
  134.       }
  135.     }
  136.     else if (newSlope>maxSlope){//if new slope is much larger than max slope
  137.       maxSlope = newSlope;
  138.       time = 0;//reset clock
  139.       noMatch = 0;
  140.       index = 0;//reset index
  141.     }
  142.     else{//slope not steep enough
  143.       noMatch++;//increment no match counter
  144.       if (noMatch>9){
  145.         reset();
  146.       }
  147.     }
  148.   }
  149.    
  150.   if (newData == 0 || newData == 1023){//if clipping
  151.     clipping = 1;//currently clipping
  152.     //Serial.println("clipping");
  153.   }
  154.   
  155.   time++;//increment timer at rate of 38.5kHz
  156.   
  157.   ampTimer++;//increment amplitude timer
  158.   if (abs(127-ADCH)>maxAmp){
  159.     maxAmp = abs(127-ADCH);
  160.   }
  161.   if (ampTimer==1000){
  162.     ampTimer = 0;
  163.     checkMaxAmp = maxAmp;
  164.     maxAmp = 0;
  165.   }
  166.   
  167. }

  168. void reset(){//clean out some variables
  169.   index = 0;//reset index
  170.   noMatch = 0;//reset match couner
  171.   maxSlope = 0;//reset slope
  172. }


  173. void checkClipping(){//manage clipping indication
  174.   if (clipping){//if currently clipping
  175.     clipping = 0;
  176.   }
  177. }


  178. void loop(){

  179.   
  180. //  checkClipping();
  181.   
  182.   
  183.   if (checkMaxAmp>ampThreshold){
  184.     frequency = 38462/float(period);//calculate frequency timer rate/period
  185.   
  186.     //print results
  187.     if ((frequency>60) && (frequency<600))
  188.     {

  189. Serial.println(frequency);




  190.   //Serial.println(int (frequency));
  191.   //|82|-96-|110|-128-|147|-171-|196|-221-|247|-288-|329|
  192. if (frequency<96)       {letter = E; ref_freq=82;}
  193. else if (frequency<128) {letter = A; ref_freq=110;}
  194. else if (frequency<171) {letter = D; ref_freq=147;}
  195. else if (frequency<221) {letter = G; ref_freq= 196;}
  196. else if (frequency<288) {letter = B; ref_freq=247;}
  197. else                    {letter = E; ref_freq=329;}

  198. bar = ref_freq-frequency;

  199. counter++;
  200. if (counter==10)
  201. {
  202. counter=0;

  203.   cli();// stop interruptions during the display printing

  204. //clear the displays
  205. lc.clearDisplay(0);
  206. lc.clearDisplay(1);
  207. lc.clearDisplay(2);
  208. lc.clearDisplay(3);

  209. //Print the Letter (A to G)
  210. lc.setColumn(3,0,characters[0+(4*letter)]);
  211. lc.setColumn(3,1,characters[1+(4*letter)]);
  212. lc.setColumn(3,2,characters[2+(4*letter)]);
  213. lc.setColumn(3,3,characters[3+(4*letter)]);

  214. //Print the tuner bar

  215. if (bar==0){
  216. lc.setColumn(0,0,0xFF); lc.setColumn(1,7,0xFF); // this is the bar
  217. lc.setRow(0,0,0xFF); lc.setRow(2,0,0xFF);       //this is a square to accentuate the perfect tuning point
  218. lc.setRow(1,0,0xFF); lc.setRow(3,0,0xFF);       //this is a square to accentuate the perfect tuning point
  219. lc.setColumn(0,7,0xFF); lc.setColumn(1,0,0xFF);}//this is a square to accentuate the perfect tuning point
  220. else if (bar==1) {lc.setColumn(0,1,0x7F); lc.setColumn(0,0,0x7F);}
  221. else if (bar==2) {lc.setColumn(0,2,0x7F); lc.setColumn(0,1,0x7F);}
  222. else if (bar==3) {lc.setColumn(0,3,0x7F); lc.setColumn(0,2,0x7F);}
  223. else if (bar==4) {lc.setColumn(0,4,0x7F); lc.setColumn(0,3,0x7F);}
  224. else if (bar==5) {lc.setColumn(0,5,0x7F); lc.setColumn(0,4,0x7F);}
  225. else if (bar==6) {lc.setColumn(0,6,0x7F); lc.setColumn(0,5,0x7F);}
  226. else if (bar==7) {lc.setColumn(0,7,0x7F); lc.setColumn(0,6,0x7F);}
  227. else if (bar==-1){lc.setColumn(1,7,0x7F); lc.setColumn(1,6,0x7F);}
  228. else if (bar==-2){lc.setColumn(1,6,0x7F); lc.setColumn(1,5,0x7F);}
  229. else if (bar==-3){lc.setColumn(1,5,0x7F); lc.setColumn(1,4,0x7F);}
  230. else if (bar==-4){lc.setColumn(1,4,0x7F); lc.setColumn(1,3,0x7F);}
  231. else if (bar==-5){lc.setColumn(1,3,0x7F); lc.setColumn(1,2,0x7F);}
  232. else if (bar==-6){lc.setColumn(1,2,0x7F); lc.setColumn(1,1,0x7F);}
  233. else if (bar==-7){lc.setColumn(1,1,0x7F); lc.setColumn(1,0,0x7F);}

  234.   sei();//enable interrupts
  235.     }
  236.   }
  237.   }
  238. }




  239. unsigned int count(unsigned int i) {
  240. unsigned int ret=1;
  241. while (i/=10) ret++;
  242. return ret;
  243. }
复制代码


tuner_standard.zip

7.93 KB, 下载次数: 1, 下载积分: E币 -5 元

积分规则
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|EDABOSS电子论坛

GMT+8, 2024-4-20 15:40 , Processed in 0.041488 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表