I have been working on a project using RF transmitters that use virtual wire and the Brain library for communicating with with a primitive EEG headset.
Everything in this setup works when tested separately. But the instant I try to put the pieces together, it doesn't seem to work. And by doesn't work, I mean it will never run the brain.update. I have a suspicion it might be related to a timer/interrupt issue. Just to be clear, I am using an Arduino Micro with the RX transmitter hooked up to pin3 and the EEG headset hooked up to pin 10.
Thanks in advance!
#include <VirtualWire.h>
#include <SoftwareSerial.h>
#include <Brain.h>
const int ledPin = 13;
int Sensor1Data;
char Sensor1CharMsg[4];
SoftwareSerial softSerial(10, 11);
Brain brain(softSerial);
void setup() {
softSerial.begin(9600);
Serial.begin(9600);
vw_setup(2000); // Bits per sec
vw_set_tx_pin(3);
pinMode(ledPin,OUTPUT);
}
void loop() {
if (brain.update()) {
Sensor1Data = brain.readAttention();
Sensor1Data = map(Sensor1Data, 0,100,0,255);
Sensor1Data = constrain(Sensor1Data, 0, 255);
itoa(Sensor1Data,Sensor1CharMsg,10);
Serial.println(Sensor1CharMsg);
}
digitalWrite(ledPin, true); // Turn on a light to show transmitting
vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(ledPin, false); // Turn off a light after transmission
delay(20);
}
Using the freeMemory library returns 1557 with that sketch loaded(not sure if this is good or bad).
Testing serial.prints in the brain.cpp is interesting. It seems to fail after some initial connection.
boolean Brain::update() {
Serial.println("update");
if (brainStream->available()) {
latestByte = brainStream->read();
Serial.println("avail?");
// Build a packet if we know we're and not just listening for sync bytes.
if (inPacket) {
Serial.println("1");
// First byte after the sync bytes is the length of the upcoming packet.
if (packetIndex == 0) {
packetLength = latestByte;
// Catch error if packet is too long
if (packetLength > MAX_PACKET_LENGTH) {
// Packet exceeded max length
// Send an error
sprintf(latestError, "ERROR: Packet too long %i", packetLength);
inPacket = false;
}
}
else if (packetIndex <= packetLength) {
Serial.println("2");
// Run of the mill data bytes.
// Print them here
// Store the byte in an array for parsing later.
packetData[packetIndex - 1] = latestByte;
// Keep building the checksum.
checksumAccumulator += latestByte;
}
else if (packetIndex > packetLength) {
// We're at the end of the data payload.
// Check the checksum.
checksum = latestByte;
checksumAccumulator = 255 - checksumAccumulator;
// Do they match?
if (checksum == checksumAccumulator) {
boolean parseSuccess = parsePacket();
if (parseSuccess) {
freshPacket = true;
}
else {
// Parsing failed, send an error.
sprintf(latestError, "ERROR: Could not parse");
// good place to print the packet if debugging
}
}
else {
// Checksum mismatch, send an error.
sprintf(latestError, "ERROR: Checksum");
// good place to print the packet if debugging
}
// End of packet
// Reset, prep for next packet
inPacket = false;
}
packetIndex++;
}
// Look for the start of the packet
if ((latestByte == 170) && (lastByte == 170) && !inPacket) {
// Start of packet
inPacket = true;
packetIndex = 0;
checksumAccumulator = 0;
Serial.println("lastbyte");
}
// Keep track of the last byte so we can find the sync byte pairs.
lastByte = latestByte;
}
if (freshPacket) {
freshPacket = false;
return true;
Serial.println("fresh??");
}
else {
return false;
}
}
I see both the update and avail prints, but it never enters into the if (inPacket) {} or any other major voids{} or booleans{} that exist in the cpp. I'm still trying to get more info from comparing this to some of the old sketches that work.
Edit: so after checking with a sketch that functions, it does indeed hit a wall at if (inPacket) {] which prevents anything else from running. I'm in way over my head here, but this means it's not able to pick up sync bytes?
updated to run through this again, tried to place a print before and after each significant if statement.
Seems like the if{}s are never true nothing ever prints from inside an if{}. Eventually the boolean Brain::update just returns false.
I wonder if trying to use the Brain library without going through softserial would help? I couldn't get it to work before, but maybe if I get my hands on an arduino Uno it would be a bit more simple.
boolean Brain::update() {
if (brainStream->available()) {
latestByte = brainStream->read();
// Build a packet if we know we're and not just listening for sync bytes.
Serial.println("in");
if (inPacket) {
// First byte after the sync bytes is the length of the upcoming packet.
if (packetIndex == 0) {
packetLength = latestByte;
// Catch error if packet is too long
if (packetLength > MAX_PACKET_LENGTH) {
// Packet exceeded max length
// Send an error
sprintf(latestError, "ERROR: Packet too long %i", packetLength);
inPacket = false;
}
}
else if (packetIndex <= packetLength) {
// Run of the mill data bytes.
// Print them here
// Store the byte in an array for parsing later.
packetData[packetIndex - 1] = latestByte;
// Keep building the checksum.
checksumAccumulator += latestByte;
}
else if (packetIndex > packetLength) {
// We're at the end of the data payload.
// Check the checksum.
checksum = latestByte;
checksumAccumulator = 255 - checksumAccumulator;
// Do they match?
if (checksum == checksumAccumulator) {
boolean parseSuccess = parsePacket();
if (parseSuccess) {
freshPacket = true;
}
else {
// Parsing failed, send an error.
sprintf(latestError, "ERROR: Could not parse");
// good place to print the packet if debugging
}
}
else {
// Checksum mismatch, send an error.
sprintf(latestError, "ERROR: Checksum");
// good place to print the packet if debugging
}
// End of packet
// Reset, prep for next packet
inPacket = false;
}
packetIndex++;
}
// Look for the start of the packet
Serial.println("last");
if ((latestByte == 170) && (lastByte == 170) && !inPacket) {
Serial.println("1");
// Start of packet
inPacket = true;
Serial.println("2");
packetIndex = 0;
checksumAccumulator = 0;
Serial.println("3");
}
// Keep track of the last byte so we can find the sync byte pairs.
Serial.println("equal");
lastByte = latestByte;
Serial.println(lastByte);
}
Serial.println("if2");
if (freshPacket) {
Serial.println("packet");
freshPacket = false;
return true;
}
else {
Serial.println("false");
return false;
}
}
boolean Brain::update() {
/// Is there anything to read?
if (brainStream->available()) {
latestByte = brainStream->read();
// Build a packet if we know we're and not just listening for sync bytes.
Serial.println("in");
But what was latestByte?
If there is never anything available to read, then clearly the VirtualWire library is causing some conflicts.
SoftwareSerial softSerial(10, 11);
I seem to recall that VirtualWire uses pins 9 and 10 as defaults Perhaps you should either make sure that all defaults VirtualWire uses are overwritten with other values, or do software serial on other pins.
Well, thats certainly interesting, lastByte is a constant string of bytes!
Is that lastByte or latestByte? Pretty small brain came up with those names. currByte and prevByte are more distinguishable and more clearly reflect where each value came from.