Forum Rule: Always post complete source code & details to reproduce any issue!
Page 8 of 18 FirstFirst ... 6 7 8 9 10 ... LastLast
Results 176 to 200 of 428

Thread: Teensy 3.x multithreading library first release

  1. #176
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    Morning tonton81. That's for the lesson. Think I am going to print this thread to a file and extract a lessons learned from all the comments/suggestions on threading.

    Thanks for the info the I2C bus. Was searching the web but gets pretty confusing, tmi sometimes. I came across this for I2c https://www.tindie.com/products/Swit...pander-board-/ and this https://shop.controleverything.com/p...c-bus-extender. Wanted to be sure I didn't need it.

    Thanks
    Mike

  2. #177
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    you will not need it, if i can run utp at 10feet in an automotive environment, im sure your arm wont be radiating an EMF field to disrupt the signal

    i too was confused about the mutex lock names, but thats just what they are, named locks, they cant be locked twice so they wait their turn. just know this if you put 2 different locks on Serial1 they will collide, thats why everything you do to serial1 you MUST keep the same mutex as other locations related to Serial1, and also note this, you can have several locks in each function, taking turns at writing data/ports spi/uart/spi, the more locks you put, the faster your sketch goes, because the lock doesnt need to do the entire function, this speeds up the data on both threads to access the ports while their both doing their functions taking turns without locking the entire duration of the function

  3. #178
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    just know this if you put 2 different locks on Serial1 they will collide, that's why everything you do to serial1 you MUST keep the same mutex as other locations related to Serial1, and also note this, you can have several locks in each function, taking turns at writing data/ports spi/uart/spi, the more locks you put, the faster your sketch goes, because the lock doesn't need to do the entire function, this speeds up the data on both threads to access the ports while their both doing their functions taking turns without locking the entire duration of the function
    That's an interesting tidbit. Now to figure out how to use that with library calls that I have that use I2C and Serial in the lib. I know somewhere in this thread we talked about it. But I think if I put the locks around the calls it should suffice.

  4. #179
    Senior Member
    Join Date
    Jan 2013
    Posts
    843
    Quote Originally Posted by tonton81 View Post
    here is a good question
    is it possible to lock 2 different mutexes before running a function since A) reads a value from i2c and B) writes update to spi bus
    ex

    Code:
    {
    Threads::Scope scope(wire1);
    Threads::Scope scope(spi1);
    if (read wire byte ) write (spi byte) <-- yes i know this isnt right but you get what i mean
    }
    will this dual lock work?
    Yes, this works, but it's dangerous. If a second thread uses the locks in the reverse order, you can get a deadlock (1st thread may have locked wire1, 2nd thread spi1 and they are stuck waiting for the other guy to release his lock).

    Code:
    {
    // 2nd thread, which will cause deadlocks
    Threads::Scope scope(spi1);
    Threads::Scope scope(wire1);
    ...
    }
    You need to make sure that all threads always acquire these nested locks in the same order.

  5. #180
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    ahh okay tni, so everywhere i need 2 or more locks, i could use same method above but have to keep the same order everywhere

    i guess its asking for trouble if we put 3 locks then

    i guess i could lock and add a local variable to store the i2c data then scope out and start a lock for the spi write
    it will eat up a byte of memory but itll be gone with the scope as well. i guess its safer not to double up scopes then

    thanks tni

  6. #181
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    mjs513: it should be possible, i havnt added the mutex locks but i have a thread writing to serial2 along with thread0, i havnt had issues yet but im sure it wont stay long as sooner or later itll walk over each other. however, it may just be a library i wrote and tested using protected variables, its working with multithreading in 2 threads, but also be aware in my previous post a few pages back, the private section of the code was definately not stable in multiple threads, once i removed private and replaced it with protected in the *.h file, its been threading great, so if your testing libraries thats one thing to look out for, i couldnt multithread my library until i changed private to protected in the *.h file
    Last edited by tonton81; 04-10-2017 at 01:05 PM.

  7. #182
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    tonton81: I was looking at that post a couple of nights ago. Right now I am writing only to either Serial or Serial4. Getting ready to attach a GPS to another Serial port and I want to thread it, but have to see what affects its going to have. First I want to make sure I understand threads and what we discussed a couple of posts back.

  8. #183
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    no problem im here almost all the time

  9. #184
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    update: in the quad function classless unlimited mcp23s17 chip control code i wrote, i added mutex lock enclosing each spi transaction, all the other calls to the function can remain untouched and theres 8 devices on that bus! its working well! all 8 chips on that bus are read/write polling great!

    this means we can just edit the library spi/i2c/uart transactions and lock them within that section, no need to touch any other of your sketch!

    this makes implementing teensythreads faster to do with many libraries and SHARING compatible! nice

    i used in my function:

    Code:
    { Threads::Scope scope(HW_SPI1);
    now if i add a shared spi devices to SPI1 bus i just need to add that above code and everything will be happy together
    Last edited by tonton81; 04-12-2017 at 08:39 PM.

  10. #185
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    @tonton81. Nice. Definitely makes lifer easier.

  11. #186
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    mjs513, yup!

    however, if your directly accessing the hardware (Wire1.write(), Wire1.read()) for example, you have no choice since those commands are not in one location, so you must scope those as well:

    { Threads::Scope scope(HW_WIRE1);

    This will be quite a bit time consuming for editing if you dont have your calls in one location, as each direct access needs to have identical lock for the same bus

    since my expander code is centralized, i only needed to lock the functions, all the calls to it are taken care of
    Last edited by tonton81; 04-13-2017 at 02:05 AM.

  12. #187
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    Now. Here's the million dollar question. If I have to devices on the same bus that each use a different library or a different class instance, if I just wrap each call to the library and each are in a different thread but I just wrap each lib call with the same lock would that be sufficient. I haven't had a chance to test that. I just started playing with calls to a GPS which is on Serial4 and printing to Serial.

    By the way decided to use to play with atomic variables since everything I have been reading is warning to stay away from volatiles for threading application.

  13. #188
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    i havnt touched my variables as of yet, just mutex, so far its running great. if you have 2+ classes accessing a library via threading, i recommend setting rivate to rotected in the *.h file as rivate didnt work at all in my testing of a library i worked on. if you use the same lock for everything, yes it will work, they will take turns passing the lock around. however, to increase performance, multiple locks can be better, like individual bus locks, as 2 or more locks can run simuletaneously since they are different, which is why i names the locks as the bus they are. example, while spi1 is locked, wire1 can still lock and run an i2c device in parallel with the spi bus lock, so you have i2c and spi happening at same time. if you keep the locks the same, the shortest thread will run more times than the longer thread but the "feel" of it all will just seem single threaded as each time it locks the other thread waits for release, and likewise, in this case its more or less a prioritized thread in a singlethreaded-like environment, kinda hard to explain but you prolly will get the idea

    the point is, while something is locked, anything else not related to it can still run in the process, only if theres no same lock is ran into, regular code and different named locks can still perform, if the other thread hits the same mutex lock it just stits there like this:

    while(1); //forever

    the moment the other thread lets go, the block releases, and the thread continues

  14. #189
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    also you can run many libraries and devices on the same spi bus, and to make it work before implemtning it, in the *.cpp file find the spi transaction sections and put your scope lock around it the SAME name as the one used for the SAME spi lock you named. this should make not only the spi bus mutex lock work but also gives you ability to work with many classes without touching your sketch code after, because youve protected the section related to accessing the bus, theres no reason to scope lock any of your code at that point

    like i said my spi1 bus has 8 spi port expanders, polled read and writing 24/7, both threads are read/write polling the gpios and/or their registers during runtime

  15. #190
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    I actually understand what you are saying and thanks for the confirmation. Since most of the fun I am having is with IMUs its probably better to put them on separate busses as opposed to the same bus with a different address. Unless of course I only have one bus.

    Have to get into the I2C lib for Teensy. Would be even nicer is there was a threaded version.

    Ok. I give up, my curiosity has gotten the better of me now. What the heck are you doing that you have so much hanging off your Teensy?

  16. #191
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309

  17. #192
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    Wow. That's a project and a half. When are you going to add obstacle avoidance, lane departure, etc

  18. #193
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    that would be overkill no?

    both screens are on separate threads, but they are both using the same SPI bus to talk to the 8 expanders. both lcds are running at 625K baud uart speeds on serial1 and serial2 and data is always flowing from teensy to lcds as the animations are manually done by teensy as opposed by the lcd itself, so I can control them. Visually you can see the difference in speeds between before and now regarding the animations. They slow down on single threading because the 70kbyte code the loop has to go through before looping again takes time, especially with canbus and i2c devices being read all the time. now the 2nd screen has it's own dedicated loop and both are working at normal speeds now.
    Last edited by tonton81; 04-13-2017 at 08:35 PM.

  19. #194
    Senior Member
    Join Date
    Sep 2015
    Location
    Taiwan, Asai. (Traditional Chinese)
    Posts
    161
    hello, sorry for asking such a question,
    but I don't know what is a "thread" yet, I'm still noob in coding.

    from the replys of this post,
    I'm guessing its kind of hardware flash paging/partition
    how's it different from choosing loop with a variable/boolean flag?
    is it writing flash to better locations after compiler, and that runs the code faster?
    or does threading means more?
    not sure are my assumings correct?

    thanks for answering

  20. #195
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    Hi Po Ting. You might want to check this YouTube video out:



    From https://www.tutorialspoint.com/cplus...ithreading.htm I got this definition.

    Multithreading is a specialized form of multitasking and a multitasking is the feature that allows your computer to run two or more programs concurrently. In general, there are two types of multitasking: process-based and thread-based.
    Process-based multitasking handles the concurrent execution of programs. Thread-based multitasking deals with the concurrent execution of pieces of the same program.

    A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread defines a separate path of execution.

  21. #196
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    tonton81. Don't want to hijack this thread but what lcd's are u using. Also, do you have a reference on the Canbus and how to use it?

    Anyway, I noticed a similar improvement in sensor responses. They seem to be return changes in say distances a lot quick and for me playing around with obstacle avoidance makes a big difference.

    Thanks
    Mike

  22. #197
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    mjs513, 4d systems ulcd-70dt and ulcd-43pt

  23. #198
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,309
    just scoped lock HW_WIRE1 everywhere where Wire1 is being used, and moved small things into the 2nd thread to clean up the loop all 12 i2c devices on Wire1 are multithreading fine on the shared bus

    I also did SPI2, even tho it's not on separate threads, so later on i can add another device on the same bus if needed
    Last edited by tonton81; 04-14-2017 at 03:57 PM.

  24. #199
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,099
    Just started working on impact of using library calls from within a thread. For the I am using my FreeIMU library with a MPU9250 and a MS5367 pressure sensor. I call one function from the freeimu library which uses the I2Cdev, MPU9250 and baro libraries. As a test I ran it first without threading and worked fine. I created a thread and called the getYawPitchRoll function which has the form getYawPitchRoll(* ypr). What happens is that it returns on set of values but the never updates. It gets stuck on one set of values. There are only sequential calls to query the sensors. Timing issue? Here is the code I used:

    Code:
    #include <Wire.h>
    #include <SPI.h>
    #include "TeensyThreads.h"
    
    #include <atomic>
    #include <I2Cdev.h>
    #include <MPU60X0.h>
    #include <BaroSensor.h>
    
    //These are mandatory
    #include <AP_Math_freeimu.h>
    #include <Butter.h>    // Butterworth filter
    #include <iCompass.h>
    #include <MovingAvarageFilter.h>
    
    //#define DEBUG
    #include "DebugUtils.h"
    #include "CommunicationUtils.h"
    #include "DCM.h"
    #include "FilteringScheme.h"
    #include "RunningAverage.h"
    #include "FreeIMU.h"
    
    #include <EEPROM.h>
    #define HAS_EEPPROM 1
    
    //char str[512];
    float ypr[3]; // yaw pitch roll
    std::atomic<float> roll, pitch, yaw;
    
    int sensor, sensor1;
    
    // Set the FreeIMU object
    FreeIMU my3IMU = FreeIMU();
    
    void setup() {
      Serial.begin(115200);
      Wire.begin();
      Wire.setClock(400000);
      
      delay(5);
      my3IMU.init(0x68, true); // the parameter enable or disable fast mode
      delay(5);
      sensor = threads.addThread(readSensor);
      threads.setTimeSlice(0, 1);
      threads.setTimeSlice(sensor, 1000);
      if (threads.getState(sensor) == Threads::RUNNING) Serial.println("Sensor 0 thread started");
    }
    
    void loop() { 
      //my3IMU.getYawPitchRoll(ypr);
      Serial.print("Sensor 0 Yaw: ");
      Serial.print(yaw);
      Serial.print(" Pitch: ");
      Serial.print(pitch);
      Serial.print(" Roll: ");
      Serial.print(roll);
      Serial.println("");
    }
    
    void readSensor(){
      float ypr[3]; // yaw pitch roll
      my3IMU.getYawPitchRoll(ypr);
      yaw = ypr[0];
      pitch = ypr[1];
      roll = ypr[2];
    }
    Don't know if I am missing something.

  25. #200
    Senior Member
    Join Date
    Jan 2013
    Posts
    843
    "readSensor()" is run once and then finishes. You need a loop inside.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •