Using SoftSerial and Virtual wire together -- Timer conflict?

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); 
 
}
#include <Brain.h>

A link would be useful.

And by doesn't work, I mean it will never run the brain.update.

Do you have some proof to back up this allegation, counselor?

There is no way that that code can NOT call brain.update(). That brain.update() never returns true is a completely different issue.

Thanks for the quick response!

The brain library is located here: GitHub - kitschpatrol/Brain: Arduino library for reading Neurosky EEG brainwave data. (Tested with the MindFlex and Force Trainer toys.)

Yes you are right, brain.update{} it never returns true, I'm testing it running a simple Serial.println to check whether it gets called.

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);
}

the code above returns a value when I comment out these lines (might be obvious, but):

vw_setup(2000);     // Bits per sec
vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
vw_wait_tx(); // Wait until the whole message is gone

And conversely when I comment out the brain.update the virtualwire works again.

I don't see anything obvious in the Brain.h or Brain.cpp file that would suggest pin, timer, or interrupt conflicts. Memory, maybe.

You need to confirm that you have enough memory.
http://playground.arduino.cc/Code/AvailableMemory

You need to add Serial.print() statements to Brain.cpp to see where Brain::update() gets hung up.

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?

        if ((latestByte == 170) && (lastByte == 170) && !inPacket) {
            // Start of packet
            inPacket = true;
            packetIndex = 0;
            checksumAccumulator = 0;
            Serial.println("lastbyte"); 
        }

Printing the value of lastByte inside the block seems like that's not the best place. Print it right after it gets a value.

    if (freshPacket) {
        freshPacket = false;
        return true;
        Serial.println("fresh??");

Printing AFTER a return?

Ha! thanks, not the brightest over here.

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!

81
0
38
187
0
32
226
0
9
41
4
0
5
0
0
0
248
170
170
32
2
200
131
24
5
51
28
0
194
214
0
247
157
0
249
249
0
123
201
0
90
225
0
80
46
0
75
235
4
0
5
0
0
0
236
170
170
32
2
200
131
24
26
10
202
4
176
230
1
26
95
11
179
168
1
148
70
170
170
32
2
200
131
24
26
219
8
3

There is definitely some kind of pattern.

170
170
32
2
200
131
24

according to this line the 170 are headers for info.

 // Look for the start of the packet
        if ((latestByte == 170) && (lastByte == 170) && !inPacket) {
            // Start of packet
            inPacket = true;
            packetIndex = 0;
            checksumAccumulator = 0;
        }

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.