Not sure if this is your problem, but setPinValues
looks weird to me:
void setPinValues(String message) {
for(int i = 1; i <= sizeof(pins) / sizeof(pins[0]); i++ ) {
String pinNumber = String(i);
if( message == pinNumber + "H\n" ) {
pinValues[i] = HIGH;
}
if( message == pinNumber + "L\n" ) {
pinValues[i] = LOW;
}
}
}
Going out of bounds
Each time you call setPinValues
, i
will range from 1
to length(pins)
, so if pins
was declared as pins[5]
, i
will be 1
, 2
, 3
, 4
and 5
. Assuming length(pins) == length(pinValues)
this is a problem in itself, because pinValues[5]
would not even exist!
pinValues[5]
only creates pinValues[0]
to pinValues[4]
(yes, I know it's weird, you're declaring 5 elements but, since C is 0-indexed, they're 0
, 1
, 2
, 3
, and 4
), so i
should NEVER reach 5 or you will be out of bounds which is undefined behavior (and might well be the source of your problems) because you're writing to the wrong memory location.
The correct way to do this is looping from 0
to i < sizeof(pins) / sizeof(pins[0])
(notice the strict less-than <
operator) which ranges from 0
to length(pins) - 1
and then just String pinNumber = String(i + 1);
. That way, 1H
will change the value of pinValues[0]
, mapping you 1-indexed serial messages to 0-indexed C arrays.
Looping is unnecessary
I'm not sure why you're looping over pins
. You're doing unnecessary work and probably hogging the uC (specially since, as Dave Tweed points out in the other answer, you're using expensive functions such as String
and string comparison with ==
).
message
has a single instance, e.g., 1H\n
so there's no loop needed. char pinNumber = message[0] - '0';
will store the integer value of the first character in pinNumber
, with which you're then able to index the array.
How does that work?
message[0]
would be a char
type (e.g. '1'
)
'0'
is also a char
, which corresponds to the ASCII value of 0 (48 in decimal).
- If
message[0]
contains the char '0'
, then the result is '0' - '0' == 48 - 48 == 0
- Since numbers are contiguous and increasing in the ASCII set the result of the subtraction is the actual number as a single byte integer.
'1' - '0' == 49 - 48 == 1
and on and on.
You might also want to reject bogus input:
if (pinNumber >= sizeof(pins) / sizeof(pins[0]))
return;
More spurious work
At each loop()
iteration you do this:
// Write to pins
for (int i = 1; i <= sizeof(pins) / sizeof(pins[0]); i++) {
digitalWrite(pins[i], pinValues[i]);
}
Which has the same problem with the out-of-bounds as before.
It also does unnecessary work, since you're writing ALL pin values, whether they changed or not! Why don't you digitalWrite(pins[pinNumber], HIGH or LOW);
directly in setPinValues
and avoid this loop? You could even get rid of the pinValues
array if you don't really need to store them (or you can keep it if you need it for some reason).
My alternative setPinValues
void setPinValue(char pin, char value) {
char pinNumber = pin - '0'; // Get the integer value of the ASCII char
if (pinNumber >= sizeof(pins) / sizeof(pins[0])) // Reject out-of-bounds input
return;
switch (value) {
case 'H':
pinValues[pinNumber] = HIGH; // Not necessary if you don't want to store the pin values
digitalWrite(pins[pinNumber], HIGH);
break;
case 'L':
pinValues[pinNumber] = LOW; // Not necessary if you don't want to store the pin values
digitalWrite(pins[pinNumber], LOW);
}
}
And then just call it from loop()
as setPinValue(message[0], message[1]);
Let me know if this solves your problem.
Ok I figured out. To those who will get into this kind of trouble, it was really the baudRate who was misconfigured into my bluetooth module. That explain why the transmission of data worked, not the reception.
The fact is I was changing the bluetooth Bps rate but not permanently, so when I was reading the bluetooth configuration it was actually diplaying the not permanently BaudRate. So typping the
SU, 96
in my bluetooth command mode resolved my issued. (My arduino was configured to send at 9600 too, of course).
Best Answer
The baud rate 57600 is a pretty marginal on an AVR (the microcontroller used) at 16 MHz, normally OK with only a bit over 2% error but some modules can be picky. The site WormFood's AVR Baud Rate Calculator shows some good tables on error percentages for various clock / baud rate combinations.
Also I just noticed Majenko's comment and he's quite right the software serial you're using will be worse at that speed so for a start try it using a hardware UART.
That Arduino runs at 5 V logic levels so if you're not using a voltage divider to drop the transmit line to 3.3 V that might be worth try first. I've read a few mixed things about whether the HC modules are 5 V tolerant on the serial lines or not and it certainly won't do any harm trying it first to see if it resolves it.
But if neither of those steps work I'd recommend getting a USB to TTL serial converter, it seems for that module you should look for one with a 3.3 V logic level like this one for Sparkfun. They are also useful for a host of other things so are generally useful to have at your disposal.