Just wanted to say I've been using the forums to learn a lot so thank you to all contributors and supporters of stack overflow.
I'm a student new to processing/arduino and I'm trying to make a processing sketch that takes serial data and graphs multiple sensor values on different graphs, while having the ability for the user to record all data into a CSV. Also I was wondering how to make a simple text box that updated and printed one of the sensor values.
A very basic snippet of my arduino serial printout code includes:
Serial.print(sensor1);
Serial.print(",");
Serial.print(sensor2);
Serial.print(",");
Serial.print(sensor3);
Serial.println(",");
//Sensor1 and 2, would be on separate graphs, and 3 would be a single printed value updated frequently.
For processing I've seen very basic examples and was wondering if what would be easier/better: to do a direct graph using the map function or to setup a cgraph and cdata arrays (saw in another example). Lastly while using a create writer or filewriter for saving data, is there a way to have new files being created rather than overwriting or appending data? Could I use an if statement to get user input text to type in the filename to avoid an overwrite?
I would be greatful for any hints or help.
You should probably send a new line character at the end:
Serial.print(sensor1);
Serial.print(",");
Serial.print(sensor2);
Serial.print(",");
Serial.print(sensor3);
Serial.println();
Once that's done you can use Serial's bufferUntil() to keep track of each line for you. Then in serialEvent() you can simply readString()
In terms of saving to a CSV file, you can append each line to an ArrayList.
(Alternatively you can used a typical String[] but you have to manually manage the line index and expand() the array when new lines come in. ArrayList may be simpler). Whenever you want to save the CSV file, you can easily convert the ArrayList to a String[] which is what saveStrings() expects. In terms of saving new files, you can simply create a timestamp string:
import processing.serial.*;
//serial port
Serial arduino;
//timestamp used for CSV filename
String timestamp;
//current CSV line received from Arduino
String currentLine = "";
//all lines received from Arduino
ArrayList<String> csvData = new ArrayList<String>();
void setup(){
try{
//be sure use the correct port/baud rate
arduino = new Serial(this,"/SERIAL_PORT_HERE",115200);
arduino.bufferUntil('\n');
}catch(Exception e){
System.err.println("Error initializing serial port!\nPlease check the PORT NAME, BAUD RATE and USB connections\nAlso close Serial Monitor or other serial port connections (if any)");
e.printStackTrace();
}
}
void draw(){
background(0);
text(currentLine,10,15);
}
void serialEvent(Serial s){
//read data from serial port
currentLine = s.readString();
//append data to be later saved as a CSV file
csvData.add(currentLine);
//process current values - update plot, not fully implemented
processCurrentLine();
}
void processCurrentLine(){
//parse and update plot here
try{
String[] values = currentLine.split(",");
printArray(values);
}catch(Exception e){
e.printStackTrace();
}
}
void saveCSV(){
//create a timestamp to be used for the CSV filename (avoiding the file being overwritten
timestamp = day()+"-"+month()+"-"+year()+" "+hour()+":"+minute()+":"+second();
println("saving CSV file");
saveStrings(timestamp+".csv",csvData.toArray(new String[csvData.size()]));
}
//save on 's' key
void keyReleased(){
if(key == 's') saveCSV();
}
//save on exit
void exit(){
saveCSV();
super.exit();
}
If you're on Windows, you might want to checkout SerialChart.
It's a nice simple Qt based UI for rendering graphcs based on CSV formatted Serial data. It should also allow you to save the data and it provides a few configuration settings too.
Update
I have recently noticed Arduino 1.6.6 (or newer) has a built in Serial Plotter
Related
Im trying to send some data using the bulkout endpoint of a usb device.
I can open the usb device (corsair k65rgb keyboard) interface 2 (which control the lighting) using createfile and SetupDiGetDeviceInterfaceDetail.
But the example code I have write data using HidD_SetFeature. And from the usb sniffer it write urb function classe interface (using the control endpoint)
but when I open corsair cue software it use urb function bulk or interrupt transfer.
So I know its possible to send bulk data. But im lost on how to do it
Thank you
I use QT 5.9 and VS2015
You could try the winusb call WinUsb_WritePipe() for transfering data using bulk transfers.
A interface handle is required before we can use WinUsb calls.It is obtained by using setupApi calls and after the required device is found.
Use CreateFile() call to open the file handle and perform WinUsb_Initialise() to obtain the interface handle.
We can use this interface handle for further WinUsb calls.For Bulk transfer we would also require pipe(Endpoint) information which can be obtained by
WinUsb_QueryPipe() call.
Check the following reference for list of winusb calls:
https://learn.microsoft.com/en-us/windows/desktop/api/winusb/
This is an example code for Bulk transfer using a winusb call.
BOOL WriteToBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG* pcbWritten)
{
if (hDeviceHandle==INVALID_HANDLE_VALUE || !pID || !pcbWritten)
{
return FALSE;
}
BOOL bResult = TRUE;
UCHAR szBuffer[] = "Hello World";
ULONG cbSize = strlen(szBuffer);
ULONG cbSent = 0;
bResult = WinUsb_WritePipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbSent, 0);
if(!bResult)
{
goto done;
}
printf("Wrote to pipe %d: %s \nActual data transferred: %d.\n", *pID, szBuffer, cbSent);
*pcbWritten = cbSent;
done:
return bResult;
}
Check the following reference for more details:
Refer:
https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/using-winusb-api-to-communicate-with-a-usb-device
https://learn.microsoft.com/en-us/windows/desktop/api/winusb/nf-winusb-winusb_writepipe
I want to use QAudioRecorder to record an audio and save as a file and display the filepath to the user. I had tried using the the example from Qt but there's no feed on the buffer value when I tested it on Android. It works on my Desktop though. Below are part of my codes:
AudioRecord::AudioRecord(QWidget *parent)
{
audioRecorder = new QAudioRecorder(this);
probe = new QAudioProbe;
connect(probe, SIGNAL(audioBufferProbed(QAudioBuffer)),
this, SLOT(processBuffer(QAudioBuffer)));
probe->setSource(audioRecorder);
}
void AudioRecord::processBuffer(const QAudioBuffer& buffer)
{
qDebug()<<"Testing Successful";
}
The processBuffer function does not seems to be called. What should I do to get the buffer value work? Is there any other way around?
Thanks!
I've a SODAQ Mbili board with a LoRa bee. I've also a GPS sensor. Below you could find how I add the bee and the sensor.
On that board I make a JSON string with the GPS coordinates and I'll send that data over the LoRa network. But How could I do that.
In the source code I've download they use next code:
LoRaModemMicrochip modem(&MODEM_SERIAL, &debugSerial);
Device libTest(&modem, &debugSerial);
void readGPSData() {
GPSSensor gpsSens(4.3, 51.222, 15.5, 0);
dumpSendResult(gpsSens);
}
void dumpSendResult(Sensor& sns) {
bool sendResult = libTest.send(sns, true);
}
I'll change this code like code below so I could send my JSON data
LoRaModemMicrochip modem(&MODEM_SERIAL, &debugSerial);
Device libTest(&modem, &debugSerial);
void readGPSData() {
String json = "My JSON code";
dumpJsonResult(json);
}
void dumpJsonResult(String& text) {
bool sendResult = libTest.send(text, true);
}
But it gives me this error:
In function void dumpJsonResult(String&):
Error: no matching function for call to Device::send(String&, bool)
bool sendResult = libTest.send(text, true);
^
Did you know how I could send JSON data to the LoRaWAN?
If you have correct NWSessionKey and APPSessionKey and so on, you could try to onboard your device over Actility's free partner zone.
https://partners.thingpark.com/
Once you do that, you would need to:
Learn how to perform a downlink
Create your own payload mechanism, such as coding your GPS over signed ints for Lat, long and Alt.
Then decode it within your device
Your device could also send ack to an Applicative Server you would plug to Actility's solution (REST-POST/JSON)
Let us know how it goes
Best regards,
What are the libraries used? I haven't found LoRaModemMicrochip object definition on sodaq site.
Have you looked at http://support.sodaq.com/sodaq-one/lorabee/?
I would strongly suggest you to not used JSON with LoRa,as this is very verbose and will use a lot of air time, while the bands where LoRa run have strong duty cycle constrains.
I want to make an audio streaming program (like phone) using the QMediaPlayer, QAudioProbe and QAudioOutput classes in Qt 5.3.0 MSVC2012 OpenGL 32bit.
This is my code:
musicPlayer = new QMediaPlayer();
musicProbe = new QAudioProbe();
musicProbe->setSource(musicPlayer);
connect(musicProbe, SIGNAL(audioBufferProbed(QAudioBuffer)),
this, SLOT(slotGetMusicData(QAudioBuffer)));
If audio data probed, the slot is actived.
void MusicPlayer::slotGetMusicData(QAudioBuffer musicBuffer)
{
/*QAudioBuffer to QByteArray*/
*musicDataBuffer = musicDataBuffer->fromRawData((char *)musicBuffer.data(),
,musicBuffer.byteCount());
/*Send Music Data*/
musicSocket->sendMudicData(*musicDataBuffer);
qDebug("send complete");
}
Using a socket, I send the data to another program.
The other program plays the music received.
QAudioOutput *audioOutput = new QAudioOutput(format, this);
QIoDevice *audioDevice = audioOutput->start();
and then, data received this slot is actived.
void BgmSocket::slotPlayBgm(QByteArray data)
{
audioDevice->write(data.data(), data.size());
}
The audio is playing well, but the sounds have a lot of static (pause sound).
How can I solve this problem?
The problem was a different frequency between the network and the playback buffer.
I solved this problem by creating a buffer with double buffering.
I need to send a long text to serial printer using Jssc library. After a few I get a full buffer error, so I thought it can be the flow control settings, because for smaller transmission everything works.
The printer can use XON/XOFF flow control configuration or CTS/RTS hardware signals.
SOFTWARE FLOW CONTROL
My jssc code to open the port is this:
serialPort.openPort();
serialPort.setParams(baud, data, stop, SerialPort.PARITY_NONE);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_XONXOFF_IN | SerialPort.FLOWCONTROL_XONXOFF_OUT);
This works only for a small text output, for longer output the printer throw a full buffer error.
HARDWARE FLOW CONTROL
I also try to switch printer to cts/rts flow control and change my code to this:
serialPort.openPort();
serialPort.setParams(baud, data, stop, SerialPort.PARITY_NONE, true, false);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT);
But nothing changes. I still get the buffer error for long output.
Than I check with a COM monitor if my printer correctly sends XOFF chars or CTS signal before filling its buffer and it well works!
At the end I tried to manually manage the output stream stopping it while CTS signal is off (using an event handler) in this way everything works also with long output.... but this is not what the flowcontrol should do automatically?
MANUAL HARDWARE FLOW CONTROL TEST
This is my manual hardware flow control test.
It uses canSend boolean var to control the output stream.
private boolean canSend=true;
public void openPort(
serialPort.openPort();
serialPort.setParams(baud, data, stop, SerialPort.PARITY_NONE, true, false);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
serialPort.addEventListener(new SerialPortReader(), SerialPort.MASK_CTS);
canSend=true;
}
public void write(byte[] content) throws Exception {
ByteArrayInputStream b= new ByteArrayInputStream (content);
byte[] bytes =new byte[OUT_BUFFER_SIZE];
int byteread=0;
while ((byteread=b.read(bytes, 0, bytes.length)) >= 0) {
if(byteread>0){
while(!canSend){
Thread.sleep(CTS_WAIT);
}
if(byteread<bytes.length){
byte[] tocopy=new byte[byteread];
System.arraycopy(bytes, 0, tocopy, 0, byteread);
serialPort.writeBytes(tocopy);
}else{
serialPort.writeBytes(bytes);
}
}
}
}
private class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
if(event.isCTS()){
canSend=event.getEventValue() == 1;
}
}
}
Seems that the flowcontrol settings is completely ignored.
What can be? Is it a jssc error a windows driver error?
I also tries to check it with getFlowControlMode() and I correctly get a values of 3 for the hardware flow control test.
At the end the problems was not the jssc library but usb to serial adapter. Changing it with a FTDI chip based adapter it works. (Moreover seems that also the last driver's release of Prolific adapter works).