Original Location: http://japan.renesasrulz.com/gr_user_forum_japanese/b/weblog/archive/2013/05/20/kurumi-tone.aspx
Owner: Okamiya Yuuki May 20, 2013
I created a piano with a PC-keyboard, piezoelectric speaker and KURUMI. I was able to perform a tune using a 10-keypad via TeraTerm. KURUMI lights up as I play do-re-mi!
When you create a sketch, make sure you select the section indicated in the red box below.For example, when using TeraTerm as the terminal software, the program will be executed when a port is specified after TeraTerm starts up. Alternately, the program will not run before the port is specified.
Copy and build the following to run the program.
#include <RLduino78.h>#define BLACK 0#define RED 1#define GREEN 2#define YELLOW 3#define BLUE 4#define PINK 5#define SKY 6#define WHITE 7
#define PIN_BZ 2
#define LED_R 22#define LED_G 23#define LED_B 24
int melody[] = { 1319, 523, 587, 659, 698, 784, 880, 988, 1047, 1175};void ledKurumi(int);
void setup(){ Serial.begin(9600); pinMode(LED_R , OUTPUT); //LED RED pinMode(LED_G , OUTPUT); //LED GREEN pinMode(LED_B , OUTPUT); //LED BLUE
//DO RE MI tone(PIN_BZ, melody[1]); delay(200); tone(PIN_BZ, melody[2]); delay(200); tone(PIN_BZ, melody[3]); delay(200); noTone(PIN_BZ);}
void loop(){ int iNum;
noTone(PIN_BZ); ledKurumi(BLACK); while(!Serial.available()); char cNum = Serial.read(); Serial.println(cNum); if ( (cNum < '0') || (cNum > '9') ){ //from char to int (0-9) iNum = 0; //illegal } else { iNum = (int)( cNum - '0' ); } ledKurumi(iNum); tone(PIN_BZ, melody[iNum]); delay(200);}
void ledKurumi(int color){ switch(color){ case BLACK: digitalWrite(LED_R, HIGH); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, HIGH); break; case RED: digitalWrite(LED_R, LOW); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, HIGH); break; case GREEN: digitalWrite(LED_R, HIGH); digitalWrite(LED_G, LOW); digitalWrite(LED_B, HIGH); break; case YELLOW: digitalWrite(LED_R, LOW); digitalWrite(LED_G, LOW); digitalWrite(LED_B, HIGH); break; case BLUE: digitalWrite(LED_R, HIGH); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, LOW); break; case PINK: digitalWrite(LED_R, LOW); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, LOW); break; case SKY: digitalWrite(LED_R, HIGH); digitalWrite(LED_G, LOW); digitalWrite(LED_B, LOW); break; case WHITE: digitalWrite(LED_R, LOW); digitalWrite(LED_G, LOW); digitalWrite(LED_B, LOW); break; case 8: digitalWrite(LED_R, LOW); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, HIGH); break; case 9: digitalWrite(LED_R, HIGH); digitalWrite(LED_G, LOW); digitalWrite(LED_B, HIGH); break; default: digitalWrite(LED_R, HIGH); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, HIGH); break; }}
COMMENTS
Fujita Nozomu
By “buzzer” do you mean piezoelectric speaker?
Okamiya Yuuki
Oops. Yes, you’re right! I fixed the wording.
Carcon 999
I have a question about the spec for the TONE function. When I change PIN3 to an output pin, a pulse is output from that pin as well when using TONE. Serial.begin(9600); pinMode(LED_R , OUTPUT); //LED RED pinMode(LED_G , OUTPUT); //LED GREEN pinMode(LED_B , OUTPUT); //LED BLUE pinMode(3 , OUTPUT);
Using the above sample, pinMode(3 , OUTPUT); <- By adding just this line,A TONE pulse is output from both PIN2 and PIN3. * Sorry. I didn’t mean to say that I switched PIN2 to PIN3. My explanation got erased somehow…
TO01, which can be assigned to PIN3, is used as the tone timer, as defined by #define TONE_TIMER PWM_PIN_3 in gr_common/include/RLduino78_mcu_depend.h.
The problem is that function
static void _startTimerChannel(uint8_t u8TimerChannel, uint16_t u16TimerMode, uint16_t u16Interval, bool bPWM, bool bInterrupt,
which is called by
void tone(uint8_t u8Pin, unsigned int u16Frequency, unsigned long u32Duration) in gr_common/RLduino78/cores/RLduino78_basic.cpp,
is coded so that the timer is output as usual, regardless of the value of argument bPWM.
if (bPWM == true) {TOM0.tom0 |= (1 << u8TimerChannel);// Timer output mode setting} else {TOM0.tom0 &= ~(1 << u8TimerChannel);// Timer output mode setting}TOL0.tol0 &= ~(1 << u8TimerChannel);// Timer output level settingTO0.to0 &= ~(1 << u8TimerChannel);// Timer output settingTOE0.toe0 |= (1 << u8TimerChannel);// Timer output enable settingTS0.ts0 |= (1 << u8TimerChannel);// Timer output operation enable setting
Since timer unit 0 channel 4 is used as Servo,gr_common/include/RLduino78_mcu_depend.h:#define SERVO_CHANNEL 4 // TM04It interferes with PWM_PIN_9 and the same problem occurs. (PWM_PIN_9 と被る の意味が良くわかりません。何がPIN_9と被る?)
Unit 0 on GR-KURUM has 8 timers. Among those timers, channel 0 is used for the PWM Mater (masterでしょうか) channel (?) and 5 other channels are used to support each hardware PWM pin. (8 timers となっていますけど、以下は6timersの話しか出てこないです。)
gr_common/include/RLduino78_mcu_depend.h:#define PWM_PIN_3 1 // TO1#define PWM_PIN_5 2 // TO2#define PWM_PIN_6 7 // TO7#define PWM_PIN_9 4 // TO4#define PWM_PIN_10 3 // TO3
If some pins are not used for PWM, the corresponding timer channel could be used for something else (supposedly). Currently, channels 1 and 4 are reserved exclusively as PWM for Tone and Servo.#define TONE_TIMER PWM_PIN_3#define SERVO_CHANNEL 4 // TM04
Channel 6 is used for software PWM. #define SW_PWM_TIMER 6
Channel 5 is hard coded for the microsecond timer.
gr_common/RLduino78/cores/RLduino78_timer.c:TT0.tt0 |= 0x0020; // Microsecond timer operation stopTMR05.tmr05 = IT_CLOCK_MODE; // Microsecond timer operation mode settingTDR05.tdr05 = INTERVAL_MICRO; // Microsecond timer frequency settingTO0.to0 &= ~0x0020; // Microsecond timer output settingTOE0.toe0 &= ~0x0020; // Microsecond timer output enable setting
The pins and timer channels used for hardware PWM correspond with each other, so that the corresponding timer channel of a pin that is not used for hardware PWM can be used for another purpose.
The timers used for Tone, Servo, software PWM and microsecond timer function as simple interval timers. The channels of those timers should be selectable by the user. However, the library currently in use requires the section after gr_common to be rewritten.
Adding the function or changing the specification so that each timer channel could be changed by the user would allow users the freedom to assign pins as they wish.
Example:SetToneTimer(6); // Hardware PWM uses 5 timer channels, software PWM uses no timer channels, so the remaining timer channel 6 can be assigned to Tone.
Above I said, “It interferes with PWM_PIN_9 and the same problem occurs.” But that doesn’t occur.
Above I said “…is coded so that the timer is output as usual, regardless of the value of argument bPWM.” Correction: “…is coded so that the timer is output as usual, regardless of the value of argument bInterrupt.
Okaymiya Yuuki
Renesas Night is coming up really soon. Fujita-san, thank you for your post. I haven’t had time to confirm it yet, please give me a little more time.
I have a suggestion for the post indicating that, “When I change PIN3 to an output pin, a pulse is output from that pin as well when using TONE.” (by Carcon 999
Try the changing the following:
gr_common/RLduino78/cores/RLduino78_basic.cpp TOL0.tol0 &= ~(1 << u8TimerChannel);// Timer output level settingTO0.to0 &= ~(1 << u8TimerChannel);// Timer output settingTOE0.toe0 |= (1 << u8TimerChannel);// Timer output enable settingTo if (bInterrupt == true) {TO0.to0 &= ~(1 << u8TimerChannel);// Timer output settingTOE0.toe0 &= ~(1 << u8TimerChannel);// Timer output disable setting} else {TOL0.tol0 &= ~(1 << u8TimerChannel);// Timer output level settingTO0.to0 &= ~(1 << u8TimerChannel);// Timer output settingTOE0.toe0 |= (1 << u8TimerChannel);// Timer output enable setting}
Fujita-san: thank you very much.I am happy to finally know that the cause of the LEDs not working properly on my board is related to TONE. No rush, but please let me know when you figure out if the library can be used to resolve the problem.※藤田さん中の人みたいですね。(笑) どういう意味でしょうか?
Okamiya YuukiI apologize for the confusion. The disturbance of D3 PWM output by tone may be due to the spec, but I didn’t expect that it would affect the port output as well. I will check out Fujita-san’s corrections and report back.
Okamiya YuukiI just checked and it looks like Fujita-san’s corrections are good. Probably at least the starred (☆ ) items below will operate, but I will make an update after further evaluation.By the way, further back Carcon 999-san’s comments got cut off. I think this is due to "<<" being mistaken as restricted characters. It happened to me as well. << are two-byte characters.
☆if (bInterrupt == true) {TO0.to0 &= ~(1 <<u8TimerChannel);// Timer output setting☆ TOE0.toe0 &= ~(1 << u8TimerChannel);// Timer output disable setting☆} else {TOL0.tol0 &= ~(1 << u8TimerChannel);// Timer output level settingTO0.to0 &= ~(1 << u8TimerChannel);// Timer output setting☆ TOE0.toe0 |= (1 << u8TimerChannel);// Timer output enable setting☆}The problem is generated because the timer for creating the tone uses TIO1, yet TIO01 is also assigned to PIN2 PWM. Although the timer should be set so that it does not output to the port when a tone is created, it was still set to output to the port. So when the corresponding port is enable, the timer for creating the tone will be output to that port as well.
Fujita NozomuAbout “<<" being mistaken as restricted characters: You can avoid this by writing &lt;&lt;But you can write # "&lt;" in single-byte characters…
So that is where I went wrong… I need to be careful about ’<<’ (two-bytes). I don’t use those characters that often, maybe I was in a hurry that day.