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

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)

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.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.