1

I am trying to control the brightness of an LED using PWM. I am also trying to make it so that when I click a button on my bluetooth app, I can get it to change the frequency of the PWM pin.

For changing the frequency, I am changing the value of the timers. When I click "30 HZ" on my bluetooth app, I am sending a value of "A", 122 HZ = "B" etc..

I hooked up a oscilloscope and changing the frequency does work.

The problem is that when I click a button, it receives A or B etc.. but it doesn't enter the switch statement every time. It is very laggy. It will also receive inaccurate numbers at times.

I think I need something in differentiating between various serial inputs? (one for choosing frequency and one for the duty cycle of the LEDs)? and also being able to enter the switch statements and then staying in there until another char is received.

Below is my code and I would appreciate any help!

const int pwmPin = 11;
const int TurnLightPin = 13;
int ledState = LOW; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 500; // interval at which to blink (milliseconds)
int dutyCycle = 0;
char state =' ';
void setup() {
 // put your setup code here, to run once:
 //Change register values to adjust PWM frequency for PWM Pins 3 and 11: 
 //TCCR2B = TCCR2B & B11111000 | B00000100; // set timer 2 divisor to 64 for PWM frequency of 490.20 Hz (The DEFAULT) 
 //TCCR2B = TCCR2B & B11111000 | B00000101; // set timer 2 divisor to 128 for PWM frequency of 245.10 Hz
 //TCCR2B = TCCR2B & B11111000 | B00000110; // set timer 2 divisor to 256 for PWM frequency of 122.55 Hz 
 //TCCR2B = TCCR2B & B11111000 | B00000111; // set timer 2 divisor to 1024 for PWM frequency of 30.64 Hz pinMode(TurnLightPin, OUTPUT);
 pinMode(TurnLightPin, OUTPUT);
 pinMode(pwmPin, OUTPUT); 
 Serial.begin(9600); // Default baudrate of bluetooth -- 9600 bits/second
 Serial.println("HC-06 Bluetooth connected!!!");
 Serial.flush();
}
void loop() {
 // check to see if it's time to blink the LED; that is, if the
 // difference between the current time and last time you blinked
 // the LED is bigger than the interval at which you want to
 // blink the LED.
 unsigned long currentMillis = millis();
 if (currentMillis - previousMillis >= interval) {
 // save the last time you blinked the LED
 previousMillis = currentMillis;
 // if the LED is off turn it on and vice-versa:
 if (ledState == LOW) {
 ledState = HIGH;
 } else {
 ledState = LOW;
 }
 // set the LED with the ledState of the variable:
 digitalWrite(TurnLightPin, ledState);
}
 //PWM Stuff:
while(Serial.available()){
 // if (Serial.available() > 0){
 state = Serial.read();
 Serial.print("State received - Before Switch Statement: ");
 Serial.println(state);
 //}
switch (state) {
case 'A':
 TCCR2B = TCCR2B & B11111000 | B00000111; // set timer 2 divisor to 1024 for PWM frequency of 30.64 Hz
 while(Serial.available() && (Serial.read() != 'B' || Serial.read() != 'C' || Serial.read() != 'D')){
 dutyCycle = Serial.parseInt();
 int pwmValue = (dutyCycle * 2.55 ); // Multiplied by 2.55 b/c sending a value between 0-100 and max PWM value is 255
 //AnalogWrite takes two arguments: (pin to write to, and value b/w 0-255)
 analogWrite(pwmPin, pwmValue); //Sets the pin to the value received
 Serial.print("A-30 HZ - PWMValue:");
 Serial.println(pwmValue);
 Serial.print("A-30 HZ - State:");
 Serial.println(state);
 }
 state = ' ';
 break;
case 'B': 
 TCCR2B = TCCR2B & B11111000 | B00000110; // set timer 2 divisor to 256 for PWM frequency of 122.55 Hz 
 while(Serial.available() && (Serial.read() != 'A' || Serial.read() != 'C' || Serial.read() != 'D')){
 dutyCycle = Serial.parseInt();
 int pwmValue = (dutyCycle * 2.55 ); // Multiplied by 2.55 b/c sending a value between 0-100 and max PWM value is 255
 //AnalogWrite takes two arguments: (pin to write to, and value b/w 0-255)
 analogWrite(pwmPin, pwmValue); //Sets the pin to the value received
 Serial.print("B-122 HZ - PWMValue:");
 Serial.println(pwmValue);
 Serial.print("B-122 HZ - State:");
 Serial.println(state);
 }
 state = ' ';
 break;
case 'C':
 TCCR2B = TCCR2B & B11111000 | B00000101; // set timer 2 divisor to 128 for PWM frequency of 245.10 Hz
 while(Serial.available() && (Serial.read() != 'A' || Serial.read() != 'B' || Serial.read() != 'D')){
 dutyCycle = Serial.parseInt();
 int pwmValue = (dutyCycle * 2.55 ); // Multiplied by 2.55 b/c sending a value between 0-100 and max PWM value is 255
 //AnalogWrite takes two arguments: (pin to write to, and value b/w 0-255)
 analogWrite(pwmPin, pwmValue); //Sets the pin to the value received
 Serial.print("C-245 HZ - PWMValue:");
 Serial.println(pwmValue);
 Serial.print("C-245 HZ - State:");
 Serial.println(state);
 }
 state = ' ';
 break;
case 'D':
 TCCR2B = TCCR2B & B11111000 | B00000100; // set timer 2 divisor to 64 for PWM frequency of 490.20 Hz (The DEFAULT) 
 while(Serial.available() && (Serial.read() != 'A' || Serial.read() != 'B' || Serial.read() != 'C')){
 dutyCycle = Serial.parseInt();
 int pwmValue = (dutyCycle * 2.55 ); // Multiplied by 2.55 b/c sending a value between 0-100 and max PWM value is 255
 //AnalogWrite takes two arguments: (pin to write to, and value b/w 0-255)
 analogWrite(pwmPin, pwmValue); //Sets the pin to the value received
 Serial.print("D-490 HZ - PWMValue:");
 Serial.println(pwmValue);
 Serial.print("D-490 HZ - State:");
 Serial.println(state);
 }
 state = ' ';
 break;
default:
 TCCR2B = TCCR2B & B11111000 | B00000110; // set timer 2 divisor to 256 for PWM frequency of 122.55 Hz 
 while(Serial.available()){
 dutyCycle = Serial.parseInt();
 int pwmValue = (dutyCycle * 2.55 ); // Multiplied by 2.55 b/c sending a value between 0-100 and max PWM value is 255
 //AnalogWrite takes two arguments: (pin to write to, and value b/w 0-255)
 analogWrite(pwmPin, pwmValue); //Sets the pin to the value received
 Serial.print("default - PWMValue:");
 Serial.println(pwmValue);
 Serial.print("Default - State:");
 Serial.println(state);
 }
 state = ' ';
 break;
 }//End of Switch Statement
 } // End of While loop for PWM
} // End of void Loop

Code Gorilla
5,6521 gold badge17 silver badges31 bronze badges
asked Jul 15, 2016 at 16:10

2 Answers 2

1

I don't like your serial parser at all. Lots of whiles, reads, places to get stuck in...

For example mine looks like:

void loop() {
 if (Serial.available()) {
 int ch = Serial.peek(); // check first character in buffer
 switch (ch) {
 case 'a' ... 'd':
 TCCR2B &= 0b11111000; // mask out prescaler (turn off timer 2)
 TCCR2B |= 0b111 - (ch - 'a'); // a => 7, b => 6, c => 5, d => 4
 Serial.read(); // remove character from buffer
 Serial.println(TCCR2B, HEX);
 break;
 case 'A' ... 'D':
 TCCR2B &= 0b11111000; // mask out prescaler (turn off timer 2)
 TCCR2B |= 0b111 - (ch - 'A'); // A => 7, B => 6, C => 5, D => 4
 Serial.read(); // remove character from buffer
 Serial.println(TCCR2B, HEX);
 break;
 case '0' ... '9':
 dutyCycle = Serial.parseInt();
 analogWrite(pwmPin, (int)(dutyCycle*2.55));
 Serial.println(dutyCycle);
 break;
 default:
 Serial.read(); // some invalid character? Drop it
 break;
 }
 }
}

However it needs some extra character after number (needed by parseInt)

answered Jul 15, 2016 at 19:32
0

i had major issues with ws2812 and the hm-10, and i couldn't get a great solution for it, and although your setup is different, it may help...

my solution was to stop things that were interrupting the interrupt, in this case, the leds, so to create;

void dataLow () {
 // drop the power on the data pins for the leds
 digitalWrite(DATA_PINA, LOW); 
 digitalWrite(DATA_PINB, LOW);
 Serial.println("DATA_PINS - LOW");
}
void dataHigh () {
 // turn the power back on for the leds
 digitalWrite(DATA_PINA, HIGH);
 digitalWrite(DATA_PINB, HIGH);
 Serial.println("DATA_PINS - HIGH");
}

and then to clean the data. i was looking for 2 numerical characters, and if i got anything else, then dump the data.

bluetooth.listen(); 
while (bluetooth.available() > 0) {
 dataLow();
 char inChar = bluetooth.read();
 // if its a character, add it to the string
 if (isDigit(inChar)) {
 inString += (char)inChar;
 }
 // if the string is longer than 2, truncate and return nothing
 if(inString.length() > 2) {
 inString[2] = '0円';
 }
 // if the serial recieves bluetooth end of line /n print string data out
 if (inChar == '\n') {
 Serial.print("String: "); Serial.println(inString.toInt());
 program=inString.toInt();
 inString = "";
 dataHigh();
 }
 // read user input from serial monitor
 if (Serial.available()){
 delay(10); // The DELAY!
 bluetooth.write(Serial.read());
 }
 }

it was still twitchy, but it mostly works.

answered Aug 15, 2016 at 11:21

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.