Serial Port: connecting to Arduino

Hi. I’m totally new to JUCE and, while I am pretty fluent in C, I am also fairly new to C++ so please bear with me if I am being stupid!

I may have taken on a tough challenge for my first JUCE ‘learning’ project :thinking: but I am trying to write a ‘simple’ GUI to send and receive ASCII data via the USB Serial connection to an Arduino.

I have been using the Serial Port module originally written by graffiti and updated by Chris Roberts.

I have managed to get a list of serial ports on my PC (Win10), add them to a combo box to let me select the port that the Arduino is connected to and the Arduino reboots in the normal way when I select the port but I’m at a loss as to how to receive the data that the Arduino is sending. It starts with a simple ASCII string terminated by a newline to identify itself. I have set the input stream to notify when a newline is received.

I’ve tried adding a Listener but what is the Serial port object that is sending the message?

Is there a way for me to post the code here? I don’t see any ‘code’ tags :cry:

I’d be very grateful for any help or suggestions.

Phil.

1 Like

It‘s as simple as pasting it here and putting three backticks ``` in the line above and below it

Regarding the question, I don’t know that module but having a quick look at the example code (which is full of memory leaks by the way :see_no_evil:) it seems that you just need to read from the SerialPortInputStream instance created for a certain port once you are notified by the change broadcaster. The SerialPortInputStream seems to inherit juce::InputStream. But as I said this is my conclusion from looking at the code for two minutes, never actually worked with it

Thanks!

The MainComponent.cpp

#include "MainComponent.h"

//==============================================================================
MainComponent::MainComponent()
{
    setSize (600, 400);
    
    addAndMakeVisible(textLabel);
    textLabel.setFont(textFont);

    addAndMakeVisible(sendButton);
    sendButton.setButtonText("Send");

    addAndMakeVisible(getButton);
    getButton.setButtonText("Get");

    addAndMakeVisible(loadButton);
    loadButton.setButtonText("Load");

    addAndMakeVisible(saveButton);
    saveButton.setButtonText("Save");

    addAndMakeVisible(serialPortMenu);
    
            
        //get a list of serial ports installed on the system, as a StringPairArray containing a friendly name and the port path
        portlist = SerialPort::getSerialPortPaths();

            DBG("There is(are) " + juce::String(portlist.size()) + " ports.");
    
            // add Serial Port names to the combo-box

    for (int i = 0; i < portlist.size(); i ++ )
        serialPortMenu.addItem(portlist.getAllValues()[i],i+1);

    
    // Set up the handler function for when the user chooses an item in the list
    serialPortMenu.onChange = [this] { serialPortMenuChanged(); };
    serialPortMenu.setSelectedId(1);
    
    getButton.onClick = [this] { getPatches(); };
    sendButton.onClick = [this] { sendPatches(); };
    saveButton.onClick = [this] { savePatches(); };
    loadButton.onClick = [this] { loadPatches(); };
  
}

MainComponent::~MainComponent()
{
}

//==============================================================================
void MainComponent::paint (juce::Graphics& g)
{
    // (Our component is opaque, so we must completely fill the background with a solid colour)


}

void MainComponent::resized()
{
    // This is called when the MainComponent is resized.
    // If you add any child components, this is where you should
    // update their positions.
    
        auto area = getLocalBounds();
        auto buttonsSpace = 4;

        auto buttonsHeight = 40;
        auto buttonsWidth = 60;
        auto dropBoxWidth = 100;

        buttonsArea = area.removeFromBottom(buttonsHeight);
        textLabel.setBounds (10, 10, getWidth() - 20, 20);
        serialPortMenu.setBounds (10, 40, dropBoxWidth, 30);
        sendButton.setBounds(buttonsArea.removeFromLeft(buttonsWidth).reduced(buttonsSpace));
        getButton.setBounds(buttonsArea.removeFromLeft(buttonsWidth).reduced(buttonsSpace));
        loadButton.setBounds(buttonsArea.removeFromLeft(buttonsWidth).reduced(buttonsSpace));
        saveButton.setBounds(buttonsArea.removeFromLeft(buttonsWidth).reduced(buttonsSpace));
}





void MainComponent::serialPortMenuChanged()
    {
        DBG("serialPortMenuChanged function called");
        pSP = new SerialPort(portlist.getAllValues()[serialPortMenu.getSelectedId() - 1], SerialPortConfig(57600, 8, SerialPortConfig::SERIALPORT_PARITY_NONE, SerialPortConfig::STOPBITS_1, SerialPortConfig::FLOWCONTROL_NONE));
		if(pSP->exists())
		{
			//create streams for reading/writing
			pOutputStream = new SerialPortOutputStream(pSP);
			pInputStream = new SerialPortInputStream(pSP);
			pOutputStream->write("hello world via serial", 22); //write some bytes
	
             
			// Ask to be notified when a new line is available:
           // pInputStream->addChangeListener(this); //we must be a ChangeListener to receive notifications
			pInputStream->setNotify(SerialPortInputStream::NOTIFY_ON_CHAR, '\n');
		
	
			//please see class definitions for other features/functions etc		
		}
    }
    

void MainComponent::getPatches()
{
    DBG("getPatches button clicked");
}


void MainComponent::sendPatches()
{
    DBG("sendPatches button clicked");
    
}

 void MainComponent::savePatches()
{
    DBG("savePatches button clicked");
}

 void MainComponent::loadPatches()
{
    DBG("loadPatches button clicked");
}

 void MainComponent::serialEvent()
 {

 }

and the .h file:

#pragma once

#include <JuceHeader.h>

//==============================================================================
/*
    This component lives inside our window, and this is where you should put all
    your controls and content.
*/
class MainComponent  : public juce::Component
   
{
    
    

        
public:
    //==============================================================================
    MainComponent();
    ~MainComponent() override;

    //==============================================================================
    void paint (juce::Graphics&) override;
    void resized() override;
    void getPatches();
    void sendPatches();
    void savePatches();
    void loadPatches();
    void serialEvent();
    
   void serialPortMenuChanged();

private:
    //==============================================================================
    // Your private member variables go here...
    juce::TextButton sendButton;
    juce::TextButton getButton;
    juce:: TextButton loadButton;
    juce::TextButton saveButton;
    juce::Rectangle<int> buttonsArea;
    juce::Label textLabel { {}, "Serial Ports" };
    juce::Font textFont   { 16.0f };
    juce::ComboBox serialPortMenu;
    juce::StringPairArray portlist;
    SerialPort * pSP;
    SerialPortOutputStream* pOutputStream;
    SerialPortInputStream* pInputStream;


    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

Hi Phil. Let me know where I can send you some code. I have a sample app that might be helpful in getting up and running. :slight_smile:

Thanks buddy,

I have sent you a message with my email address.

Phil.

Hi guys! I want to know if you could pass me some code that you used, because i am trying to conect the arduino with JUCE. My objetive is read values of temperature and humedity with the Arduino and then show them in an interface realize in juce. I really apreciate if someone can help me. Thanks, and sorry for my einglish. :slight_smile:

sent

I gave up Juce in the end and switched to Python. Sorry I can’t be of any help to you :cry:

Phil.

Dont worry, i appreciate your attention, and thanks @cpr2323 for the code, i will try to do something with it :slight_smile:

2 Likes