I am writing a printing function synonymous with 3D printing which reads an SD file and then acts on each line of the data. Below is my code: (variables have been assigned previously and code works).
void Print() {
Home_Y();
delay(100);
Home_X();
px = 75;
py = 67.5;
Read_SD(); //Opens the SD card
while (printFile.available() > 0) {
char character = printFile.read();
if (bufferposition < buffer_size - 1)
{
Buffer[bufferposition++] = character;
}
if (character == '\n')
{
Buffer[bufferposition] = 0;
//****************// add in command here
bufferposition = 0;
}
}
//The code then continues down further.
I want to run a separate function at the point in the code marked "//***//" continuously until switched off later in the code. My problem is that I can only run this function once, multiple calls would just delay the following processes.
My Question:
I was wondering if there was any way around this, or to simulate two functions running simultaneously. I have read somewhere about interrupts and timing delays, but wasn't sure if I was heading down the right path?
Related
I am writing a code to capture serial readings from the Arduino to C++
Is there a way to capture the readings line by line and then store it into an array? I have read another post similar to mine, but I am still unable to apply it.
Any help is greatly appreciated, thank you.
Environment setup:
Arduino UNO
ADXL 335 accelerometer
Ubuntu 16.04
C++
[Updated] applied solution from Bart
Cpp file
The reason why I added the "for-loop with print and break" is to analyze the array contents.
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
using namespace std;
char serialPortFilename[] = "/dev/ttyACM0";
int main()
{
char readBuffer[1024];
FILE *serPort = fopen(serialPortFilename, "r");
if (serPort == NULL)
{
printf("ERROR");
return 0;
}
while(1)
{
usleep(1000); //sync up Linux and Arduino
memset(readBuffer, 0, 1024);
fread(readBuffer, sizeof(char),1024,serPort);
for(int i=0; i<1024; i++){
printf("%c",readBuffer[i]);
}
break;
}
return 0;
}
Ino file
Fetching data from the Accelerometer
#include <stdio.h>
const int xPin = A0;
const int yPin = A1;
const int zPin = A2;
void setup() {
Serial.begin(9600);
}
void loop() {
int x = 0, y = 0, z = 0;
x = analogRead(xPin);
y = analogRead(yPin);
z = analogRead(zPin);
char buffer[16];
int n;
n = sprintf(buffer,"<%d,%d,%d>",x,y,z);
Serial.write(buffer);
}
Results
Running the code for three times
Click Here
The ideal outputs should be
<a,b,c><a,b,c><a,b,c>...
but right now, some of the outputs has the values inside "corrupted" (please see the fourth line from the top).
Even if use the start and end markers to determine a correct dataset, the data within the set is still wrong. I suspect the issue lies with the char array from C++, due to it being unsynchronized with Arduino. Else I need to send by Bytes from Arduino (not really sure how)
When dealing with two programs running on different processors they will never start sending/receiving at the same time. What you likely see is not that the results are merged wrong it is more likely the reading program started and stopped half way through the data.
When sending data over a line it is best that you:
On the Arduino:
First frame the data.
Send the frame.
On Linux:
Read in data in a buffer.
Search the buffer for a complete frame and deframe.
1. Framing the data
With framing the data I mean that you need a structure which you can recognize and validate on the receiving side. For example you could add the characters STX and ETX as control characters around your data. When the length of your data varies it is also required to send this.
In the following example we take that the data array is never longer than 255 bytes. This means that you can store the length in a single byte. Below you see pseudo code of how a frame could look like:
STX LENGTH DATA_ARRAY ETX
The total length of the bytes which will be send are thus the length of the data plus three.
2. Sending
Next you do not use println but Serial.write(buf, len) instead.
3. Receiving
On the receiving side you have a buffer in which all data received will be appended.
4. Deframing
Next each time new data has been added search for an STX character, assume the next character is the length. Using the length +1 you should find a ETX. If so you have found a valid frame and you can use the data. Next remove it from the buffer.
for(uint32_t i = 0; i < (buffer.size() - 2); ++i)
{
if(STX == buffer[i])
{
uint8_t length = buffer[i+2];
if(buffer.size() > (i + length + 3) && (ETX == buffer[i + length + 2]))
{
// Do something with the data.
// Clear the buffer from every thing before i + length + 3
buffer.clear(0, i + length + 3);
// Break the loop as by clearing the data the current index becomes invalid.
break;
}
}
}
For an example also using a Cyclic Redundancy Check (CRC) see here
I am currently working on a little Arduino project, which is using an infrared temperature sensor for measuring certain surface temperatures.
The hardware works perfectly and also simply reading analog signals with analogRead() works fine, but using this simple function for filtering the measured analog values to get better results just doesn't get along with the Arduino.
Every time the sketch running this function is uploaded to the Arduino (Pro Micro), the program just gets stuck and disables the Arduino, so that it has to be reset before appearing again in the "Ports" Menu as a COM Port.
Here is the simple function in which I cannot find the bug:
int TemperatureDifferenceSensor::measureRawFilteredTemperatureValue(int numberOfMeasurements) {
int temperatureMeasurementValueSum = 0;
int maxMeasuredTempValue = 0;
int minMeasuredTempValue = 0;
for (int i = 0; i < numberOfMeasurements; ++i) {
int measuredTemperatureValue = analogRead(analogObjectTempPin);
temperatureMeasurementValueSum += measuredTemperatureValue;
if (measuredTemperatureValue > maxMeasuredTempValue) {
maxMeasuredTempValue = measuredTemperatureValue;
} else if (measuredTemperatureValue < minMeasuredTempValue) {
minMeasuredTempValue = measuredTemperatureValue;
}
// A small delay, to not measure the same or similar value every time...
delay(10);
}
temperatureMeasurementValueSum -= maxMeasuredTempValue;
temperatureMeasurementValueSum -= minMeasuredTempValue;
int temperatureMeasurementAverageValue = (int) (temperatureMeasurementValueSum / (numberOfMeasurements - 2));
return temperatureMeasurementAverageValue;
}
If analogRead and delay works as you expected, it should be somewhat ok. One big issue with the function is that it can't be called with argument 2. This would cause zero-division exception and probably also a black hole. Why not something like:
...
} // the for-loop closes here.
if (numberOfMeasurements == 0)
return 0;
// Must have at least 3 measurements in order to remove 2 of them.
else if (numberOfMeasurements > 2)
{
temperatureMeasurementValueSum -= maxMeasuredTempValue;
temperatureMeasurementValueSum -= minMeasuredTempValue;
numberOfMeasurements -= 2; // Compensate removing two measurements.
}
// Average is sum divided by measurements.
int temperatureMeasurementAverageValue = temperatureMeasurementValueSum / numberOfMeasurements;
return temperatureMeasurementAverageValue;
Specific problem
I am trying to communicate between a Python script and my Arduino Pro Mini using serial with a USB cable. In Python I can read what the Arduino writes but the Arduino can either not read what the Python writes or it is reading it in a form that I can't process. The most obvious way this manifests itself is when I try to write what the Arduino has just read from Python, to Python. Nothing gets displayed in Python.
My Arduino sketch appears to work just fine when I work with it in the Serial Monitor, i.e. it can read and write so I suspect it is something at the Python end. What's causing this?
Details
I want to be able test how quickly I can send 64 byte-long pieces of information to my Arduino. To do this I wrote a Python script that could should be able to periodically send various information to my Arduino. I can change the period and thus test what kind of speed I can get.
However, despite the fact that my Arduino sketch works just fine with Serial Monitor, i.e. I can send it information and read information from it, I can't get it to work with Python.
With my Python script I can open the connection and read what the Arduino writes, but for some reason there is a problem with writing from Python. I have tried the following but none of them have worked:
Using an Uno instead of a Pro Mini.
Putting a Serial.println() statement in my get_data() function. Nothing gets printed.
Sending a string with the format "T(number);" and using sscanf() to extract the number. Using an if statement to examine the number and turn an onboard LED on. Did not work.
Sending a string beginning with "T" and using an if statement to see if it is stored in raw_data[]. It isn't.
Writing the data from Python at different times (i.e. using a longer delay).
Writing from Python using device.write(b"mystring") and device.write("mystring".encode())
I'm at a loss for what to try next…
Python (2.7) code
import serial, time, random, string
device = serial.Serial('/dev/tty.usbserial-A105YOZX', baudrate = 38400)
initial_time = time.time()
current_time = time.time()
counter = 0
control = 0
while counter < 1000:
current_time = time.time()
if current_time - initial_time > 0.1:
initial_time = current_time
counter += 1
device.read()
if current_time - initial_time > 1 and control == 0:
device.write(b"Message being sent")
control = 1
Arduino code
#define RAW_LEN 64 //max length of incoming string (buffer size is only 64 bytes)
//variables for incoming data
char raw_data[RAW_LEN];
int raw_data_i = 0; //index
unsigned long my_time;
int control = 0;
int for_print;
int get_data(int i) {
//fills up raw_data[] with serial data. Clears raw_data if it gets too long
if (Serial.available()>0) {
raw_data[i] = Serial.read();
Serial.println(raw_data[i]);
//Serial.println(raw_data[i]);
if (i<RAW_LEN-1){
i++;
}
}
return i;
}
void clear_data() {
//clears raw_data and resets raw_data_i
raw_data_i = 0;
memset(raw_data,'\0',RAW_LEN-1);
}
//print functions
void raw_print(char data[]) {
Serial.println("Received data: ");
//if (raw_data[0] == 'T') {digitalWrite(LED_BUILTIN, HIGH);}
for (int i=0; i< RAW_LEN;i++) {
Serial.println(data[i]);
}
}
void setup() {
Serial.begin(38400);
Serial.println("Restart");
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
}
void loop() {
my_time = millis();
raw_data_i = get_data(raw_data_i);
//clear raw_data if it gets full
if (raw_data_i == RAW_LEN-1) {
clear_data();
}
if (my_time > 5000 && control == 0) {
Serial.println("Here");
raw_print(raw_data);
control = 1;
}
}
The problem turned out to be in the Python code. In while loop the first if statement is True after 0.1s, and then executes 9 more times before the second if statement is True.
The problem with this is that device.read() just hangs if it does not receive a character. Because I wasn't sending enough characters from the Arduino the Python code paused at the device.read() and never got to the second if statement.
An annoying mistake that took a while to figure out, hopefully this question and answer will save someone else a lot of debugging time.
I have an Arduino Uno set up to sense the light level and draw to a text file via Processing when it gets dark. I'd like to modify the Processing code to interrupt the draw loop for five seconds and then restart the draw loop. This will continuously write and overwrite the .txt file but that's not important right now.
The purpose of this excercise is to understand how to insert a break into the endless draw loop. I'm still very much a newbie to programming and am trying to wrap my head around how commands interact with eath other. Can anyone help me understand how to make this work? Eample code would be great but I'd also be happy with a conceptual description of how it's supposed to work...learn by doing and all.
I've tried putting the void draw() loop within a void loop() but it erred out. Am I on the right path?
<setup...mySerial and createWriter to path/file.txt>{
}
void draw() { //this is what needs to terminate & restart
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed and end
I believe what you're looking for is called a "state machine".
Make a variable that you can use to store a time value, then compare that to the current time to see if 5s have passed.
uint32_t last_trigger = 0; // millis() returns an unsigned, 32-bit integer
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (millis() - last_trigger > 5000) { // 5000 milliseconds
last_trigger = millis(); // update last_trigger
Serial.print("last triggered at "); // report findings
Serial.print(last_trigger);
Serial.println(" milliseconds");
}
}
http://www.arduino.cc/en/Reference/Millis
If you aren't worried about really tight timing, the easy solution is to use the delay function. http://www.arduino.cc/en/Reference/Delay
The following might be a simple sketch that would do what you want. Adjust it as needed.
void setup()
{
Serial.begin(9600); // initialize serial routines
}
void loop()
{
int a = analogRead(0); // read the value of lightness
Serial.println(a); // tell processing what the value is
delay(5000); // wait for a 5 seconds
}
I'm trying to establish a SerialPort connection which transfers 16 bit data packages at a rate of 10-20 kHz. Im programming this in C++/CLI. The sender just enters an infinte while-loop after recieving the letter "s" and constantly sends 2 bytes with the data.
A Problem with the sending side is very unlikely, since a more simple approach works perfectly but too slow (in this approach, the reciever sends always an "a" first, and then gets 1 package consisting of 2 bytes. It leads to a speed of around 500Hz).
Here is the important part of this working but slow approach:
public: SerialPort^ port;
in main:
Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
port = gcnew SerialPort("COM16",384000,p,8,s);
port->Open();
and then doing as often as wanted:
port->Write("a");
int i = port->ReadByte();
int j = port->ReadByte();
This is now the actual approach im working with:
static int values[1000000];
static int counter = 0;
void reader(void)
{
SerialPort^ port;
Parity p = (Parity)Enum::Parse(Parity::typeid, "None");
StopBits s = (StopBits)Enum::Parse(StopBits::typeid, "1");
port = gcnew SerialPort("COM16",384000,p,8,s);
port->Open();
unsigned int i = 0;
unsigned int j = 0;
port->Write("s"); //with this command, the sender starts to send constantly
while(true)
{
i = port->ReadByte();
j = port->ReadByte();
values[counter] = j + (i*256);
counter++;
}
}
in main:
Thread^ readThread = gcnew Thread(gcnew ThreadStart(reader));
readThread->Start();
The counter increases (much more) rapidly at a rate of 18472 packages/s, but the values are somehow wrong.
Here is an example:
The value should look like this, with the last 4 bits changing randomly (its a signal of an analogue-digital converter):
111111001100111
Here are some values of the threaded solution given in the code:
1110011001100111
1110011000100111
1110011000100111
1110011000100111
So it looks like the connection reads the data in the middle of the package (to be exact: 3 bits too late). What can i do? I want to avoid a solution where this error is fixed later in the code while reading the packages like this, because I don't know if the the shifting error gets worse when I edit the reading code later, which I will do most likely.
Thanks in advance,
Nikolas
PS: If this helps, here is the code of the sender-side (an AtMega168), written in C.
uint8_t activate = 0;
void uart_puti16(uint16_t val) //function that writes the data to serial port
{
while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
nop(); // wait 1 cycle
UDR0 = val >> 8; //write first byte to sending register
while ( !( UCSR0A & (1<<UDRE0)) ) //wait until serial port is ready
nop(); // wait 1 cycle
UDR0 = val & 0xFF; //write second byte to sending register
}
in main:
while(1)
{
if(active == 1)
{
uart_puti16(read()); //read is the function that gives a 16bit data set
}
}
ISR(USART_RX_vect) //interrupt-handler for a recieved byte
{
if(UDR0 == 'a') //if only 1 single data package is requested
{
uart_puti16(read());
}
if(UDR0 == 's') //for activating constant sending
{
active = 1;
}
if(UDR0 == 'e') //for deactivating constant sending
{
active = 0;
}
}
At the given bit rate of 384,000 you should get 38,400 bytes of data (8 bits of real data plus 2 framing bits) per second, or 19,200 two-byte values per second.
How fast is counter increasing in both instances? I would expect any modern computer to keep up with that rate whether using events or directly polling.
You do not show your simpler approach which is stated to work. I suggest you post that.
Also, set a breakpoint at the line
values[counter] = j + (i*256);
There, inspect i and j. Share the values you see for those variables on the very first iteration through the loop.
This is a guess based entirely on reading the code at http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx#Y228. With this caveat out of the way, here's my guess:
Your event handler is being called when data is available to read -- but you are only consuming two bytes of the available data. Your event handler may only be called every 1024 bytes. Or something similar. You might need to consume all the available data in the event handler for your program to continue as expected.
Try to re-write your handler to include a loop that reads until there is no more data available to consume.