2

i am fairly new to the field of IOT. I am setting up a sensor with teensy for reading up its data and transmitting over using serial communication to system where using python I am reading the data and storing it into a database.

The problem I am facing is when i check my program using arduino serial monitor I am getting insane sample speed like 10k readings are done in 40 milli seconds but when i try to read the same program using python it is not even giving me more than 1000 readings per second and that too without the database code with it it only reads 200 samples per second. Is there any way i can increase this sample rate or do i have to set any extra parameters for communication through serial ?

Here is my code for teensy :

int i;

elapsedMillis sinceTest1;

void setup()
{

  Serial.begin(2000000); // USB is always 12 Mbit/sec

  i = 0;

  delay(5000);

  Serial.println("Setup Called"); 

Serial.flush();

}

void loop()
{

  if (i == 0 || i == 500000)
  {

    Serial.println(sinceTest1);

  }

  Serial.println(i);

  //Serial.println(Serial.baud());

  i++;

}

For python :

import serial
import pymysql
from datetime import datetime
import time
import signal
import sys


class ReadLine:
    def __init__(self, s):
        self.buf = bytearray()
        self.s = s

    def readline(self):
        i = self.buf.find(b"\n")
        if i >= 0:
            r = self.buf[:i+1]
            self.buf = self.buf[i+1:]
            return r
        while True:
            i = max(1, min(2048, self.s.in_waiting))
            data = self.s.read(i)
            i = data.find(b"\n")
            if i >= 0:
                r = self.buf + data[:i+1]
                self.buf[0:] = data[i+1:]
                return r
            else:
                self.buf.extend(data)


ser = serial.Serial(
    port='COM5',\
    baudrate=2000000,\
    #baudrate=9600,\
    #parity=serial.PARITY_NONE,\
    #stopbits=serial.STOPBITS_ONE,\
    #bytesize=serial.EIGHTBITS,\
        #timeout=0
        )

print("connected to: " + ser.portstr)
count=1
#this will store the line
line = []

#database connection
connection = pymysql.connect(host="localhost", user="root", passwd="", database="tempDatabase")
cursor = connection.cursor()


checker = 0

rl = ReadLine(ser)
while True:

   time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
   print(time)
   print(checker)
   print(rl.readline())


   insert1 = ("INSERT INTO tempinfo(value,test,counter) VALUES('{}','{}','{}');".format(33.5, time,checker)) #.format(data[0])
   insert2 = ("INSERT INTO urlsync(textvalue,sync) VALUES('http://www.myname.com/value.php?&value={}&time={}',0);".format(33.5,time)) #.format(data[0])

   cursor.execute(insert1)
   cursor.execute(insert2)

   connection.commit()
   checker += 1


connection.close()
time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(time )
ser.close()

P.S : 1000 samples per second is the rate I am getting when I am not using the commands for database, including them I am getting around 250 samples per second only.

Any help or suggestion is appreciated, thank you.

Hadi
  • 307
  • 6
  • 20

1 Answers1

3

First off, great question. The issue you are facing is loaded with learning opportunities.

Let's go one by one:

-You are now in the position to understand the difference between a microcontroller and a computer. The microcontroller in its most basic form (if you are running bare-metal code, even if it's not very efficient code, like on an Arduino) will do just one thing, and particularly when it's hardware-related (like reading or writing to UARTs) it will do it very efficiently. On a desktop computer, on the other hand, you have layer upon layer of tasks running simultaneously (operating system background tasks, updating the screen and whatnot). With so many things happening at the same time and if you don't establish priorities, it will be very difficult to accurately predict what will exactly happen and when. So it's not only your Python code that is running, there will be many more things that will come up and interrupt the flow of your user task. If you are hoping to read data from the UART buffer at a stable (or at least predictable) speed, that will never happen with the architecture you are using at the moment.

-Even if you manage to strip down your OS to the bare minimum, kill all processes, go on a terminal with no graphics whatsoever... you still have to deal with the uncertainty of what you are doing on your own Python code (that's why you see better performance with the Arduino serial monitor, which is not doing anything other than removing data from the buffer). On your Python code, you are sequentially reading from the port, trying to find a particular character (line feed) and then attaching the data you read to a list. If you want to improve performance, you need to either just read data and store it for offline processing or look at multithreading (if you have a thread of your program dedicated to only reading from the buffer and you do further processing on a separate thread you could improve significantly the throughput, particularly if you set priorities right).

-Last, but actually, most importantly, you should ask yourself: Do I really need to read data from my sensor at 2 Mbps? If the answer is yes, and your sensor is not a video camera, I'm afraid you need to take a step back and look at the following concepts: sensor bandwidth and dynamic response. After you do that, the next question is: how fast is your sensor updating its output and why? is that update rate meaningful? I can give you a couple of references here. First, imagine you have a temperature sensor to read and record the temperature in an oven. Does it make sense to sample values from the sensor at 1 MHz (1 million readings per second) if the temperature in the oven is changing at a rate of 10 degrees C per minute or even 100 degrees per second? Is your sensor even able to react so fast (that where its dynamic response comes into play)? My guess: probably not. Many industrial devices integrate dozens of sensors to control critical processes and send all data through a 1.5 Mbps link (pretty standard for Profibus, for instance).

Marcos G.
  • 3,371
  • 2
  • 8
  • 16
  • Thank you for really informative reading, I got the concept regarding to the reading part. So if i change my system over to raspberry pi with only one python code running on it, will it improve the output ? Also, I really need to keep up with that rate so I will try running a high priority thread of the program dedicated to only reading data from the buffer and see what point I am at. Also, are the C++ libraries faster than python ones or both gives almost the same output, I am also learning about different libraries to see what can be improved. – Hadi Dec 02 '19 at 12:41
  • oh and for the baud rate as it is teensy so it is not making much difference at the sender side as teensy is sending at 12 Mbps. I was just meddling up with on the receiver side to see if it makes much difference. I will try doing multi threading in the system to check on the results. – Hadi Dec 02 '19 at 12:43
  • You are welcome. I think you should be able to get the full rate, even with Python, but it very much depends on the configuration of your system (Linux version, how loaded it is and the like). With Python I was able to get up to 1.5 Mbps but it wasn't on a RPi.. – Marcos G. Dec 02 '19 at 13:40
  • Thank you, can you please direct me to a tutorial or informative article related to it or if possible write down the scenario in words like what thing i can use or take precautions of to get maximum output from the system or RPi. Thank you – Hadi Dec 02 '19 at 14:40
  • There are many resources, you can start here at SO, see for instance [this question](https://www.google.com/url?sa=t&source=web&rct=j&url=https://raspberrypi.stackexchange.com/questions/44065/scoring-a-higher-baud-rate-in-serial-pi-to-pi-communication&ved=2ahUKEwjMitbl1pfmAhV98eAKHYz-ANkQjjgwCnoECAQQAQ&usg=AOvVaw18DGXQgA8DB-BjA52kT-80) just use a search engine. I will post more links if I find something useful. – Marcos G. Dec 02 '19 at 19:20
  • I forgot to mention that these fast baud rates might also be am issue for the Teensy, you might need to look a DMA transfers, see [here](https://forum.pjrc.com/threads/46696-Serial-communication-at-high-baudrates) – Marcos G. Dec 02 '19 at 19:27
  • Thank you, I will look through them. Also, teensy is kind of bypassing and sending at 12 Mbps right away the main issue is at the receiving end as serial monitor is receiving it fully. – Hadi Dec 03 '19 at 09:07
  • I don't really know what exactly you are trying to do here so it's not easy to say but I don't think your Teensy is sending data at 12 Mbps, it's just shoving it as fast as it can. I also doubt you can print on the serial monitor that fast. Maybe it would be better if you open a new question once you figure out the multiple thread issue and explain clearly what you are doing – Marcos G. Dec 03 '19 at 12:46
  • That is, of course, unless what you want to do is receive a long meaningless sequence of numbers at very high rate with no other purpose – Marcos G. Dec 03 '19 at 12:47