Receive input from Arduino Uno


#1

Currently my Arduino’s built-in LED will light up when I press an external button, but how can I use this on an openFrameworks program? In other words, how could my oF program detect that the button has been pushed so then I could do something with that signal?


#2

You’d need to install the standard firmata onto the Arduino and then look into the example in examples/communication/firmataExample.

What you’re looking for is the ofArduino class, detailed documentation is here.


#3

is there a way I could do it without using firmata?


#4

Yes, but probably more effort required that way than just using firmata.

You can print to the Serial port from the Arduino and then use your ofApp to read those messages. But the default ofSerial class can only read bytes so to get meaningful data out of your Arduino, it’s a pretty long process.

I did something like this using ofxIO and ofxSerial some time ago (which was again based on some example I can’t remember where I found that now…) - you can take a look if you want here, but honestly, Firmata would be the best way to go.


#5

I’m an intern and the team I’m working with does not want to use firmata, so I have to work without it. So in the example you gave me, what specifically should I be looking at?


#6

Required addons: ofxIO and ofxSerial.

In my ofApp.h file you’ll find a class called SerialMessage and then some functions and variables. The serial message class you can just copy paste from there. The rest I’ve broken down below.

void onSerialBuffer(const ofx::IO::SerialBufferEventArgs& args);
void onSerialError(const ofx::IO::SerialBufferErrorEventArgs& args);
    
ofx::IO::BufferedSerialDevice device;
    
std::vector<SerialMessage> serialMessages;

In the ofApp.cpp you can find how it comes together,
ofApp::setup() has this block

 std::vector<ofx::IO::SerialDeviceInfo> devicesInfo = ofx::IO::SerialDeviceUtils::listDevices();
    
    ofLogNotice("ofApp::setup") << "Connected Devices: ";
    
    for (std::size_t i = 0; i < devicesInfo.size(); ++i)
    {
        ofLogNotice("ofApp::setup") << "\t" << devicesInfo[i];
    }
    
    if (!devicesInfo.empty())
    {
        // Connect to the first matching device.
        bool success = device.setup(devicesInfo[0], 9600);
        
        if(success)
        {
            device.registerAllEvents(this);
            ofLogNotice("ofApp::setup") << "Successfully setup " << devicesInfo[0];
        }
        else
        {
            ofLogNotice("ofApp::setup") << "Unable to setup " << devicesInfo[0];
        }
    }
    else
    {
        ofLogNotice("ofApp::setup") << "No devices connected.";
    }

ofApp::update then gets the messages,

  auto iter = serialMessages.begin();
    
    // Cycle through each of our messages and delete those that have expired.
    while (iter != serialMessages.end()){
        iter->fade -= 1;
        
        if (iter->fade < 0){
            iter = serialMessages.erase(iter);
        } else {
            auto m = iter->message;
            
            /*
            m is the message received on the serial port.
            depending on what messages you're sending and how it's formatted,
            you'd need to parse it and use it whichever you want.
            */
            
            if (!iter->exception.empty()){
                std::cout << "error?!" << std::endl;
            }
            ++iter;
        }
    }

And the other two functions that are required,

//--------------------------------------------------------------
void ofApp::onSerialBuffer(const ofx::IO::SerialBufferEventArgs& args)
{
    // Buffers will show up here when the marker character is found.
    SerialMessage message(args.getBuffer().toString(), "", 500);
    serialMessages.push_back(message);
}

//---------------------------------------------------------------
void ofApp::onSerialError(const ofx::IO::SerialBufferErrorEventArgs& args)
{
    // Errors and their corresponding buffer (if any) will show up here.
    SerialMessage message(args.getBuffer().toString(),
                          args.getException().displayText(),
                          500);
    serialMessages.push_back(message);
}

//--------------------------------------------------------------

#7

Note that this is only one way communication though, from the Arduino to the computer.