1

I am using an RFduino and an iOS application to control some RGB LEDs.

This is how I'm sending a string command to the module:

- (IBAction)fadeButtonPressed:(id)sender {
    [rfduino send:[@"fade" dataUsingEncoding:NSUTF8StringEncoding]];
}

These command(s) are coming back just fine on the RFduino side:

void RFduinoBLE_onReceive(char *data, int len) {
  if (strncmp(data, "fade", 4) == 0) {
    // begin fading chosen LED colour
  }
}

Is there a better way of executing multiple functions on Arduino? It seems to me that there should be a better way of doing what I'm trying to do.

Originally for example I was getting an issue where the "fade" string was coming back as "fadek" so I used strncmp(data, "fade", 4) instead of strcmp(data, "fade") and this fixed the issue.

I guess I'd like a way of cleaning up my code and perhaps make it easier to introduce new bits of functionality depending on which strings are coming back.

The functions I would like to be able to do would be controlling of the RGB colours and then Fading or Blinking that particular chosen colour.

What if I wanted to introduce faster blinking? Rather than setting another command integer and adding another condition is there a cleaner approach?

The selection of the colours is set by selection of a color wheel within my iOS application. This is working fine. The problem is that the Blinking and Fading does not blink/fade the selected colour (command 0).

Here is my entire sketch so far:

#include <RFduinoBLE.h>

// Pin 2 on the RGB LED.
int rgb2_pin = 2; // red
int rgb3_pin = 3; // green
int rgb4_pin = 4; // blue
int brightness = 0;
int fadeAmount = 5;

// Command properties.
int command = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);

  // Setup the LEDs for output.
  pinMode(rgb2_pin, OUTPUT);
  pinMode(rgb3_pin, OUTPUT);
  pinMode(rgb4_pin, OUTPUT);

  // This is the data we want to appear in the advertisement
  // (the deviceName length plus the advertisement length must be <= 18 bytes.
  RFduinoBLE.advertisementData = "rgb";

  // Start the BLE stack.
  RFduinoBLE.begin();
}

void loop() {
  if (command == 1) { // Fade in/out chosen colour.
    analogWrite(rgb2_pin, brightness);
    analogWrite(rgb3_pin, brightness);
    analogWrite(rgb4_pin, brightness);

    // Change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // Reverse the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
      fadeAmount = -fadeAmount ;
    }

    // Wait for 30 milliseconds to see the dimming effect
    delay(30);
  } else if (command == 2) { // Blink
    digitalWrite(rgb2_pin, HIGH);
    digitalWrite(rgb3_pin, HIGH);
    digitalWrite(rgb4_pin, HIGH);
    delay(200);
    digitalWrite(rgb2_pin, LOW);
    digitalWrite(rgb3_pin, LOW);
    digitalWrite(rgb4_pin, LOW);
    delay(200);
  }
}

void RFduinoBLE_onConnect() {}

void RFduinoBLE_onDisconnect() {}

void RFduinoBLE_onReceive(char *data, int len) {
  Serial.println(data);

  // Each transmission should contain an RGB triple.
  if (strncmp(data, "fade", 4) == 0) {
    command = 1;
  } else if (strncmp(data, "blink", 5) == 0) {
    command = 2;
  } else { // Change colour.
    // Reset other functions.
    command = 0;

    if (len >= 3) {
      // Get the RGB values.
      uint8_t red = data[0];
      uint8_t green = data[1];
      uint8_t blue = data[2];

      // Set PWM for each LED.
      analogWrite(rgb2_pin, red);
      analogWrite(rgb3_pin, green);
      analogWrite(rgb4_pin, blue);
    }
  }

  Serial.println(command);
}
  • +1 for the way you've posted your question. I hate it when people don't write comments in their script. But you did write comments! – Handoko Jun 12 '14 at 7:27
1

Ended up going with something like this:

#include <RFduinoBLE.h>

// State properties.
int state = 1;
char command;
String hexstring;

// RGB pins.
int redPin = 2;
int grnPin = 3;
int bluPin = 4;

// Setup function to set RGB pins to OUTPUT pins.
void setup () {
  pinMode(redPin, OUTPUT);
  pinMode(grnPin, OUTPUT);
  pinMode(bluPin, OUTPUT);

  // This is the data we want to appear in the advertisement
  // (the deviceName length plus the advertisement length must be <= 18 bytes.
  RFduinoBLE.deviceName = "iOS";
  RFduinoBLE.advertisementInterval = MILLISECONDS(300);
  RFduinoBLE.txPowerLevel = -20;
  RFduinoBLE.advertisementData = "rgb";

  // Start the BLE stack.
  RFduinoBLE.begin();
}

void loop () {
  switch (command) {
    case 1:
      // Blink.
    break;
    case 2:
      // Fade.
    break;
  }

  //RFduino_ULPDelay(INFINITE);
}

// Converts HEX as a String to actual HEX values.
// This is needed to properly convert the ASCII value to the hex
// value of each character.
byte getVal (char c) {
  if (c >= '0' && c <= '9') return (byte)(c - '0');
  else return (byte)(c - 'a' + 10);
}

// Process each function/command.
void processCommand (int command, String hex) {
  switch (command) {
    case 'b':
      command = 1; // Set blink mode.
    break;
    case 'f':
      command = 2; // Set fade mode.
    break;
    case 'c':
      // We put together 2 characters as is
      // done with HEX notation and set the color.
      byte red = getVal(hex.charAt(1)) + (getVal(hex.charAt(0)) << 4);
      byte green = getVal(hex.charAt(3)) + (getVal(hex.charAt(2)) << 4);
      byte blue = getVal(hex.charAt(5)) + (getVal(hex.charAt(4)) << 4);

      // Set the color.
      setColor (red, green, blue);
    break;
  }
}

// Sets the color of each RGB pin.
void setColor (byte red, byte green, byte blue) {
  analogWrite(redPin, red);
  analogWrite(grnPin, green);
  analogWrite(bluPin, blue);
  delay(200);
}

// This function returns data from the radio.
void RFduinoBLE_onReceive (char *data, int len) {
  for (int i = 0; i < len; i++) {
    stateMachine(data[i]);
  }
}

// Main state machine function, which processes
// data depending on the bytes received.
void stateMachine (char data) {
  switch (state) {
    case 1:
      if (data == 1) {
        state = 2;
      }
    break;
    case 2:
      if (data == 'b' || data == 'f' || data == 'c') {
        command = data;
        hexstring = "";
        state = 3;
      } else if (data != 1) { // Stay in state 2 if we received another 0x01.
        state = 1;
      }
    break;
    case 3:
      if ((data >= 'a' && data <= 'z') || (data >= '0' && data <= '9')) {
        hexstring = hexstring + data;
        if (hexstring.length() == 6) {
          state = 4;
        }
      } else if (data == 1) {
        state = 2;
      } else {
        state = 1;
      }
    break;
    case 4:
      if (data == 3) {
        processCommand(command, hexstring);
        state = 1;
      } else if (data == 1) {
        state = 2;
      } else {
        state = 1;
      }
    break;
  }
}
  • Does the delay(), millis() etc. work on the RFduino? – iQt Jun 11 '14 at 14:39
  • @Phataas: Not sure, why? – fuzz Jun 12 '14 at 0:53
  • 1
    I saw you removed them. – iQt Jun 12 '14 at 6:20
  • @Phataas: Oh, I just noticed that. I'll add them back in after the analogWrite() calls. – fuzz Jun 12 '14 at 6:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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