Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSerialport readyRead() for measuring revolutions
Forum Updated to NodeBB v4.3 + New Features

QSerialport readyRead() for measuring revolutions

Scheduled Pinned Locked Moved Solved General and Desktop
21 Posts 4 Posters 1.7k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    herrgross
    wrote on last edited by herrgross
    #1

    Hello all,

    I am trying to measure the revolutions of a motor sent from my ARDUINO to QSerialPort by using the readyRead-Signal. ARDUINO sends just one byte (val '1') at a time per revolution.
    I connected the readyRead-Signal to my receive-method:

    QObject::connect(port, SIGNAL(readyRead()), this, SLOT(dataRx()));
    

    In that method I measure (a.o.) the time between SIGNALS and store them in a list:

        now = std::chrono::system_clock::now();
        rxTimepoints->push_back(now.time_since_epoch().count());
    

    Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO (the values in the list should continually decrease as the motor is speeding up, but between two correct values of 180000-40000 microseconds there is always a value of 12000-4000 µs.
    How can that happen? How can I get rid of that doubling?

    Thank you for helping...

    Pl45m4P JonBJ 3 Replies Last reply
    0
    • H herrgross

      @JonB well, thanks for your help so far... I'll keep trying

      H Offline
      H Offline
      herrgross
      wrote on last edited by herrgross
      #21

      @herrgross got it!!!!
      in the arduino code the interrupt must be set to RISING instead of HIGH, so it's only sending when the state of the interruptpin c h a n g e s to HIGH

        attachInterrupt(digitalPinToInterrupt(interruptPin), impuls, RISING);
      
      

      thank you all!!

      1 Reply Last reply
      0
      • Ronel_qtmasterR Offline
        Ronel_qtmasterR Offline
        Ronel_qtmaster
        wrote on last edited by
        #2

        Hi.You will need to compare both codes to see how you manage time.if you use for instance delay or millis in arduino that has an impact.That doubling can also be due to the baud rate.make sure that the ports use the same baud rate

        H 1 Reply Last reply
        0
        • H herrgross

          Hello all,

          I am trying to measure the revolutions of a motor sent from my ARDUINO to QSerialPort by using the readyRead-Signal. ARDUINO sends just one byte (val '1') at a time per revolution.
          I connected the readyRead-Signal to my receive-method:

          QObject::connect(port, SIGNAL(readyRead()), this, SLOT(dataRx()));
          

          In that method I measure (a.o.) the time between SIGNALS and store them in a list:

              now = std::chrono::system_clock::now();
              rxTimepoints->push_back(now.time_since_epoch().count());
          

          Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO (the values in the list should continually decrease as the motor is speeding up, but between two correct values of 180000-40000 microseconds there is always a value of 12000-4000 µs.
          How can that happen? How can I get rid of that doubling?

          Thank you for helping...

          Pl45m4P Offline
          Pl45m4P Offline
          Pl45m4
          wrote on last edited by
          #3

          @herrgross

          How fast is your motor spinning?
          I doubt you can (correctly) measure the time for every single rev, when the motors spins at like 30.000 rpm.


          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          H 1 Reply Last reply
          0
          • Ronel_qtmasterR Ronel_qtmaster

            Hi.You will need to compare both codes to see how you manage time.if you use for instance delay or millis in arduino that has an impact.That doubling can also be due to the baud rate.make sure that the ports use the same baud rate

            H Offline
            H Offline
            herrgross
            wrote on last edited by herrgross
            #4

            @Ronel_qtmaster baudrate is the same for both arduino and qt-programm(9600). Maybe I try with a higher one and see if something changes, but I don't expect so... Arduino is sending from an ISR, so there should be no timeproblem:

            void impuls() {
                if (Serial.availableForWrite()) {
                  Serial.write(1);
                };
            };
            
            Ronel_qtmasterR 1 Reply Last reply
            0
            • Pl45m4P Pl45m4

              @herrgross

              How fast is your motor spinning?
              I doubt you can (correctly) measure the time for every single rev, when the motors spins at like 30.000 rpm.

              H Offline
              H Offline
              herrgross
              wrote on last edited by herrgross
              #5

              @Pl45m4
              at testing I'm not spinning higher than 30 rps = 1800 rpm. I think that should be no problem, as there is plenty of time in between pulses

              1 Reply Last reply
              0
              • H herrgross

                @Ronel_qtmaster baudrate is the same for both arduino and qt-programm(9600). Maybe I try with a higher one and see if something changes, but I don't expect so... Arduino is sending from an ISR, so there should be no timeproblem:

                void impuls() {
                    if (Serial.availableForWrite()) {
                      Serial.write(1);
                    };
                };
                
                Ronel_qtmasterR Offline
                Ronel_qtmasterR Offline
                Ronel_qtmaster
                wrote on last edited by
                #6

                @herrgross now how is your code in arduino?

                H 1 Reply Last reply
                0
                • Ronel_qtmasterR Ronel_qtmaster

                  @herrgross now how is your code in arduino?

                  H Offline
                  H Offline
                  herrgross
                  wrote on last edited by
                  #7

                  @Ronel_qtmaster here's the complete Arduino code:

                  char incomingBytes[2];
                  
                  int motorPin = 3;  // motor connected to digital pin 3 (PWM)
                  int bremsPin = 13;
                  // Drehzahlmessung
                  int interruptPin = 2;  // Hallsensor to pin 2
                  int pwmsend = 0;
                  
                  void setup() {
                    pinMode(motorPin, OUTPUT);
                    //Löschen der Timer/Counter Control Register A und B
                    TCCR1A = 0;
                    TCCR1B = 0;
                    //Modus Phase correct PWM-Mode 10 Bit einstellen
                    TCCR1A |= (1 << WGM10) | (1 << WGM11);
                    //Vorteiler auf 8 setzen
                    TCCR1B |= (1 << CS11);
                    //Nichtinvertiertes PWM-Signal setzen
                    TCCR1A |= (1 << COM1A1); 
                    //PWM-Pin 9 als Ausgang definieren
                    DDRB |= (1 << DDB1);
                  
                    pinMode(bremsPin, OUTPUT);
                    pinMode(interruptPin, INPUT_PULLUP);
                    attachInterrupt(digitalPinToInterrupt(interruptPin), impuls, HIGH);
                  
                    Serial.begin(9600);
                  }
                  
                  
                  void loop() {
                    OCR1A = 00;
                    if (Serial.available()) {
                      Serial.readBytes(incomingBytes, 2);
                      if (incomingBytes[0] == 4) {
                        //analogWrite(motorPin, 0);
                        OCR1A = 0;           //setzt pin9 auf 0
                        digitalWrite(bremsPin, HIGH);
                      };
                      // pwm senden
                      if (incomingBytes[0] != 4) {
                        int pwmsendnew;
                        pwmsendnew = int(incomingBytes[0])*256 + int(incomingBytes[1]);
                        if (pwmsendnew != pwmsend) {
                          pwmsend = pwmsendnew;
                          digitalWrite(bremsPin, LOW);
                          analogWrite(motorPin, pwmsend);
                          OCR1A = pwmsend;
                        };
                      };
                    };
                  };
                  
                  void impuls() {
                      if (Serial.availableForWrite()) {
                        Serial.write(1);
                      };
                  };
                  
                  Ronel_qtmasterR 1 Reply Last reply
                  0
                  • H herrgross

                    @Ronel_qtmaster here's the complete Arduino code:

                    char incomingBytes[2];
                    
                    int motorPin = 3;  // motor connected to digital pin 3 (PWM)
                    int bremsPin = 13;
                    // Drehzahlmessung
                    int interruptPin = 2;  // Hallsensor to pin 2
                    int pwmsend = 0;
                    
                    void setup() {
                      pinMode(motorPin, OUTPUT);
                      //Löschen der Timer/Counter Control Register A und B
                      TCCR1A = 0;
                      TCCR1B = 0;
                      //Modus Phase correct PWM-Mode 10 Bit einstellen
                      TCCR1A |= (1 << WGM10) | (1 << WGM11);
                      //Vorteiler auf 8 setzen
                      TCCR1B |= (1 << CS11);
                      //Nichtinvertiertes PWM-Signal setzen
                      TCCR1A |= (1 << COM1A1); 
                      //PWM-Pin 9 als Ausgang definieren
                      DDRB |= (1 << DDB1);
                    
                      pinMode(bremsPin, OUTPUT);
                      pinMode(interruptPin, INPUT_PULLUP);
                      attachInterrupt(digitalPinToInterrupt(interruptPin), impuls, HIGH);
                    
                      Serial.begin(9600);
                    }
                    
                    
                    void loop() {
                      OCR1A = 00;
                      if (Serial.available()) {
                        Serial.readBytes(incomingBytes, 2);
                        if (incomingBytes[0] == 4) {
                          //analogWrite(motorPin, 0);
                          OCR1A = 0;           //setzt pin9 auf 0
                          digitalWrite(bremsPin, HIGH);
                        };
                        // pwm senden
                        if (incomingBytes[0] != 4) {
                          int pwmsendnew;
                          pwmsendnew = int(incomingBytes[0])*256 + int(incomingBytes[1]);
                          if (pwmsendnew != pwmsend) {
                            pwmsend = pwmsendnew;
                            digitalWrite(bremsPin, LOW);
                            analogWrite(motorPin, pwmsend);
                            OCR1A = pwmsend;
                          };
                        };
                      };
                    };
                    
                    void impuls() {
                        if (Serial.availableForWrite()) {
                          Serial.write(1);
                        };
                    };
                    
                    Ronel_qtmasterR Offline
                    Ronel_qtmasterR Offline
                    Ronel_qtmaster
                    wrote on last edited by
                    #8

                    @herrgross reading your code remind me of something.You have that doubling behavior because you consider the values sent by arduino as byte and it does not take the entire values for intance the next line character "/r/n"

                    read all the serial values per line and as String and the doubling behavior will go

                    H 1 Reply Last reply
                    0
                    • Ronel_qtmasterR Ronel_qtmaster

                      @herrgross reading your code remind me of something.You have that doubling behavior because you consider the values sent by arduino as byte and it does not take the entire values for intance the next line character "/r/n"

                      read all the serial values per line and as String and the doubling behavior will go

                      H Offline
                      H Offline
                      herrgross
                      wrote on last edited by herrgross
                      #9

                      @Ronel_qtmaster thank you for the nice idea ... but it did not solve the problem..... anyhow I tried to control what's actually arriving with readall() into a QByteArray and the checking the size of the array and reading the data. There was nothing arriving than the '1' sent by arduino, no endline character or other

                      Ronel_qtmasterR Pl45m4P 2 Replies Last reply
                      0
                      • H herrgross

                        @Ronel_qtmaster thank you for the nice idea ... but it did not solve the problem..... anyhow I tried to control what's actually arriving with readall() into a QByteArray and the checking the size of the array and reading the data. There was nothing arriving than the '1' sent by arduino, no endline character or other

                        Ronel_qtmasterR Offline
                        Ronel_qtmasterR Offline
                        Ronel_qtmaster
                        wrote on last edited by
                        #10

                        @herrgross okay.I was only pointing that the data sent to qt through serial port have to be a string to avoid doubling.Also , it is not recommend to read data from both arduino and qt.One should send and the other receive.

                        1 Reply Last reply
                        0
                        • H herrgross

                          Hello all,

                          I am trying to measure the revolutions of a motor sent from my ARDUINO to QSerialPort by using the readyRead-Signal. ARDUINO sends just one byte (val '1') at a time per revolution.
                          I connected the readyRead-Signal to my receive-method:

                          QObject::connect(port, SIGNAL(readyRead()), this, SLOT(dataRx()));
                          

                          In that method I measure (a.o.) the time between SIGNALS and store them in a list:

                              now = std::chrono::system_clock::now();
                              rxTimepoints->push_back(now.time_since_epoch().count());
                          

                          Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO (the values in the list should continually decrease as the motor is speeding up, but between two correct values of 180000-40000 microseconds there is always a value of 12000-4000 µs.
                          How can that happen? How can I get rid of that doubling?

                          Thank you for helping...

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #11

                          @herrgross said in QSerialport readyRead() for measuring revolutions:

                          Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO

                          Can you show a minimal example? For example, you realize that if you execute that connect() statement twice in your code, somewhere, your slot would get called twice? Are you saying that the sender sends different values each time and you see the same bytes twice as pairs (like 1,1,10,10,100,100,...)? Ah, no, it's 1 every time: suggest you change that (e.g. just increment each time) so you see different values. Does your dataRx() read whatever has been received? What is bytesAvailable() reporting each time? I am starting by trying to discover whether you are seeing twice as many bytes actually sent from Arduino vs readyRead() signal being fired twice vs your slot being called twice.

                          H 1 Reply Last reply
                          0
                          • H herrgross

                            @Ronel_qtmaster thank you for the nice idea ... but it did not solve the problem..... anyhow I tried to control what's actually arriving with readall() into a QByteArray and the checking the size of the array and reading the data. There was nothing arriving than the '1' sent by arduino, no endline character or other

                            Pl45m4P Offline
                            Pl45m4P Offline
                            Pl45m4
                            wrote on last edited by
                            #12

                            @herrgross

                            I still assume the signals are coming in delayed (due to serialPort or signal event queue) and because of that your slot restarts the timer and therefore you have significantly shorter timespans in between.
                            Just a guess without analysing your code.


                            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                            ~E. W. Dijkstra

                            H 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @herrgross said in QSerialport readyRead() for measuring revolutions:

                              Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO

                              Can you show a minimal example? For example, you realize that if you execute that connect() statement twice in your code, somewhere, your slot would get called twice? Are you saying that the sender sends different values each time and you see the same bytes twice as pairs (like 1,1,10,10,100,100,...)? Ah, no, it's 1 every time: suggest you change that (e.g. just increment each time) so you see different values. Does your dataRx() read whatever has been received? What is bytesAvailable() reporting each time? I am starting by trying to discover whether you are seeing twice as many bytes actually sent from Arduino vs readyRead() signal being fired twice vs your slot being called twice.

                              H Offline
                              H Offline
                              herrgross
                              wrote on last edited by herrgross
                              #13

                              @JonB I allready searched if I connected twice... could not find that.
                              here's some of the list I get:
                              f4498c3e-56d6-423b-8810-b4401e8e35b8-image.png

                              and here's the code of my dataRx:

                              void Sirene::dataRx()
                              {
                                  if (port->bytesAvailable() > 0)
                                  {
                                      QByteArray data = port->readAll();
                                      QString value;
                                      value = QString::number(data[0]);
                                      statusBar()->showMessage(value);
                                      data.clear();
                                  }
                              
                                  now = std::chrono::system_clock::now();
                              
                                  rxTimepoints->push_back(now.time_since_epoch().count());
                              }
                              
                              JonBJ 1 Reply Last reply
                              0
                              • H herrgross

                                @JonB I allready searched if I connected twice... could not find that.
                                here's some of the list I get:
                                f4498c3e-56d6-423b-8810-b4401e8e35b8-image.png

                                and here's the code of my dataRx:

                                void Sirene::dataRx()
                                {
                                    if (port->bytesAvailable() > 0)
                                    {
                                        QByteArray data = port->readAll();
                                        QString value;
                                        value = QString::number(data[0]);
                                        statusBar()->showMessage(value);
                                        data.clear();
                                    }
                                
                                    now = std::chrono::system_clock::now();
                                
                                    rxTimepoints->push_back(now.time_since_epoch().count());
                                }
                                
                                JonBJ Offline
                                JonBJ Offline
                                JonB
                                wrote on last edited by
                                #14

                                @herrgross
                                That's a lot of code; if you want to debug I would suggest a much smaller example.

                                You haven't shown whether the port->bytesAvailable() > 0 is followed every time dataRx() is called. You haven't shown the value you receive which I thought you were changing from always being 1 --- you send it to the statusbar, which isn't very helpful.

                                I don't understand your timing numbers (now, now-before), I don't see how that helps you tell whether readyRead() is being emitted twice per byte input.

                                I suggest you reduce this to simple code illustrating what is going on.

                                H 1 Reply Last reply
                                0
                                • JonBJ JonB

                                  @herrgross
                                  That's a lot of code; if you want to debug I would suggest a much smaller example.

                                  You haven't shown whether the port->bytesAvailable() > 0 is followed every time dataRx() is called. You haven't shown the value you receive which I thought you were changing from always being 1 --- you send it to the statusbar, which isn't very helpful.

                                  I don't understand your timing numbers (now, now-before), I don't see how that helps you tell whether readyRead() is being emitted twice per byte input.

                                  I suggest you reduce this to simple code illustrating what is going on.

                                  H Offline
                                  H Offline
                                  herrgross
                                  wrote on last edited by herrgross
                                  #15

                                  @JonB ok, I reduced the code to what is necessary... (edited above)
                                  the now and now - before in the list are :
                                  now = std::chrono::system_clock::now();
                                  and that value minus the previous now-value (which is the timespan between these two time_points)
                                  So when the motor speeds up these values should continuously decrease, as the timespan between each call shoud be getting smaller.
                                  I changed now the arduino, so it sends each time an increased value,
                                  and in my statusbar (althoug not very pretty) I can see, that the value of QByteArray[0] is raising by 2 every call (so I get 2,4,6,8,10...)
                                  that should not happen I guess...

                                  1 Reply Last reply
                                  0
                                  • Pl45m4P Pl45m4

                                    @herrgross

                                    I still assume the signals are coming in delayed (due to serialPort or signal event queue) and because of that your slot restarts the timer and therefore you have significantly shorter timespans in between.
                                    Just a guess without analysing your code.

                                    H Offline
                                    H Offline
                                    herrgross
                                    wrote on last edited by
                                    #16

                                    @Pl45m4 there is no timer being started by the slot...

                                    1 Reply Last reply
                                    0
                                    • H herrgross

                                      Hello all,

                                      I am trying to measure the revolutions of a motor sent from my ARDUINO to QSerialPort by using the readyRead-Signal. ARDUINO sends just one byte (val '1') at a time per revolution.
                                      I connected the readyRead-Signal to my receive-method:

                                      QObject::connect(port, SIGNAL(readyRead()), this, SLOT(dataRx()));
                                      

                                      In that method I measure (a.o.) the time between SIGNALS and store them in a list:

                                          now = std::chrono::system_clock::now();
                                          rxTimepoints->push_back(now.time_since_epoch().count());
                                      

                                      Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO (the values in the list should continually decrease as the motor is speeding up, but between two correct values of 180000-40000 microseconds there is always a value of 12000-4000 µs.
                                      How can that happen? How can I get rid of that doubling?

                                      Thank you for helping...

                                      JonBJ Offline
                                      JonBJ Offline
                                      JonB
                                      wrote on last edited by JonB
                                      #17

                                      @herrgross said in QSerialport readyRead() for measuring revolutions:
                                      Originally you said:

                                      Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO

                                      Now you say:

                                      I can see, that the value of QByteArray[0] is raising by 2 every call (so I get 2,4,6,8,10...)

                                      which sounds more like "dataRx seems to be called only once per 2 bytes sent by the ARDUINO".

                                      As I've said, you need to find out what the actual case is. Get that sorted out before you concentrate on your timings.

                                      H 1 Reply Last reply
                                      0
                                      • JonBJ JonB

                                        @herrgross said in QSerialport readyRead() for measuring revolutions:
                                        Originally you said:

                                        Looking at this list I find that dataRx seems to be called twice per byte sent by the ARDUINO

                                        Now you say:

                                        I can see, that the value of QByteArray[0] is raising by 2 every call (so I get 2,4,6,8,10...)

                                        which sounds more like "dataRx seems to be called only once per 2 bytes sent by the ARDUINO".

                                        As I've said, you need to find out what the actual case is. Get that sorted out before you concentrate on your timings.

                                        H Offline
                                        H Offline
                                        herrgross
                                        wrote on last edited by
                                        #18

                                        @JonB what would you suggest how I can find out? I'm stuck in this since yesterday and run out of ideas...

                                        JonBJ 1 Reply Last reply
                                        0
                                        • H herrgross

                                          @JonB what would you suggest how I can find out? I'm stuck in this since yesterday and run out of ideas...

                                          JonBJ Offline
                                          JonBJ Offline
                                          JonB
                                          wrote on last edited by JonB
                                          #19

                                          @herrgross
                                          I don't know what your problem is. I have not seen convincing evidence that readyRead() is being emitted any more (or less) than it should be. You could write simpler code to verify that if you wish, or not. Only you know what your timing figures mean, I do not. I don't know that readyRead() signal is a reliable means of measuring timings in real time. I don't understand hardware and have no idea what an Arduino is :)

                                          H 1 Reply Last reply
                                          0
                                          • JonBJ JonB

                                            @herrgross
                                            I don't know what your problem is. I have not seen convincing evidence that readyRead() is being emitted any more (or less) than it should be. You could write simpler code to verify that if you wish, or not. Only you know what your timing figures mean, I do not. I don't know that readyRead() signal is a reliable means of measuring timings in real time. I don't understand hardware and have no idea what an Arduino is :)

                                            H Offline
                                            H Offline
                                            herrgross
                                            wrote on last edited by
                                            #20

                                            @JonB well, thanks for your help so far... I'll keep trying

                                            H 1 Reply Last reply
                                            0

                                            • Login

                                            • Login or register to search.
                                            • First post
                                              Last post
                                            0
                                            • Categories
                                            • Recent
                                            • Tags
                                            • Popular
                                            • Users
                                            • Groups
                                            • Search
                                            • Get Qt Extensions
                                            • Unsolved