Dual Teensy Dual LIDAR IoT Frankenstein project

Status
Not open for further replies.

amensch

Well-known member
Hello All,

Apologies in advance, I know this is something simple stupid.

Just received the first run of some new PCB's which hold two Teensies, and have connectors for Benewake LIDARS. It feeds an IoT board underneath with a linux system, and has a cell modem sandwiched in. I'm just past the phase where you make sure the boards agree with the schematics. Phew. All good.

IMG_20200131_100055155.jpg

The initial program was a simple 'onlining' program which just toggled various pins to check the PCB layout. And now I'm bringing over some code to actually read the LIDARS and dump to the Arduino serial monitor.

Next step is to read LIDAR data from Serial2 and Serial4, which will be reformatted by the Teensy 4.0 and sent to uarts Serial1 & Serial3, which are connected to the Linux board below. Eventually the T4.0 will do the algorithmic math on the incoming data to lessen the burden on the Linux board below.

So here's the issue..... I suddenly started getting this compile error, and am just not seeing the problem.


Teensy Loader could not find the file 2BEN2STT40_200131.ino

quitexit status 1
Error compiling for board Teensy 4.0.


Here's the code:
View attachment 2BEN2STT40_200131.zip

The code was just compiling a couple hours ago! True, I made some mods in to LIDAR_IO.cpp as a quick and dirty way to read the LIDARS, but duh, I am just not seeing the problem.

I'm running Arduino IDE 1.8.10 (1.8.11 I think is too new?)

Thank in Advance for looking, and I hope you enjoy the project.
 
continued from above......

Follow-up: It appears to be an environment problem? Blinky.ino gives the same error. Namely
Code:
Teensy Loader could not find the file Blinky2.ino

quitexit status 1
Error compiling for board Teensy 4.0.

BUT, Why would the Teensy Loader complain, as I didn't even try to upload, I merely ran Verify/Compile.


When I switch port and target to a Teensy 3.2, it compiles fine.

So.... I went back to the project I posted above, and compiled for Teensy 3.2, and it did behave differently, and noticed things did seem to compile, then failed at linking with serial4 function calls. Teensy 3.2 wouldn't support Serial4.calls, so understandable.

So.... switching the target back to Teensy 4.0 verbose compiler output looks OK I think, but ends with the same error.....
Code:
 Teensy Loader could not find the file 2BEN2STT40_200131.ino

quitexit status 1
Error compiling for board Teensy 4.0.
I'm wondering why the Teensy Loader would even complain, as I didn't even try to upload, I merely ran Verify/Compile. ??
 
Last edited:
Another update...

Sure enough, it did appear to link and write the hex file
Capture.PNG

But the other directories were empty. I opened the .hex file and it looked OK (as near as one can tell unless you're at a super-deep machine language level!)

Dunno, thought it a good clue. Am I posting in the right place?

Thank You,
John
 
OK, that's interesting....I closed the teensy loader, and hit the Verify/Compile checkmark (ctrl-R) at the upper left of the IDE, NOT the upload arrow next to it. The result was that the loader did open!

AND, it compiled normally, no errors! So, I hit the LOAD arrow (ctrl-U) and indeed it loaded the compiled code!

So, there is something a little weird going on here...... Perhaps it's related to having two Teensies, a T3.2 and a T4.0 plugged into two USB ports simultaneously, and perhaps that confused the loader somehow? Anyway, I'm compiling again, but there might be some subtle thing going on here, so I'll keep an eye on it & report under the 'bugs' forum.
Regards to all this Feb 1, groundhog day eve. :p
-John
 
IDE 1.8.11 is now supported with the recent release of TeensyDuino 1.50.

When a Verify is done as seen it does open TeensyLoader and passes over the HEX filename. When it works here are the finl lines form console:
Code:
"T:\\arduino-1.8.11\\hardware\\teensy/../tools/teensy_post_compile" -file=T4_MemoryInfo.ino "-path=T:\\TEMP\\arduino_build_681505" "-tools=T:\\arduino-1.8.11\\hardware\\teensy/../tools/" -board=TEENSY40
Opening Teensy Loader...

"T:\\arduino-1.8.11\\hardware\\teensy/../tools/arm/bin/arm-none-eabi-size" -A "T:\\TEMP\\arduino_build_681505/T4_MemoryInfo.ino.elf"
Sketch uses 34304 bytes (1%) of program storage space. Maximum is 2031616 bytes.
Global variables use 45748 bytes (8%) of dynamic memory, leaving 478540 bytes for local variables. Maximum is 524288 bytes.

There should also be an ELF file created if all works, and a few other files too. And only the 'libraries' folder was empty here because none are used in this sketch.

It just worked here with NO Teensy online. It also did not complain when compiled for T_4 when the T_3.2 was online and selected - for Verify build TeensyLoader does not do a board type verify. It seems there was some issue in building everything to show the errors above.

Doing a clean install of IDE 1.8.11 and TD 1.50 should make sure all is in order for building.
 
Thanks defragster. Good to know TeensyDuino 1.5 is out. Also that calling and passing over the loader is normal.

I have a bit of a program design question I've been thinking about.....how to structure continuous reads of the serial ports. It's 9 bytes of data coming in at 100Hz from two ports 24/7. Could you suggest the best forum in which to post? Here somewhere, or perhaps stackexchange? I think here people will be more familiar with the Teensy 4.0's 4 byte buffer and how to make sure I keep it clear.

Thank You,
John
 
Thanks defragster. Good to know TeensyDuino 1.5 is out. Also that calling and passing over the loader is normal.

I have a bit of a program design question I've been thinking about.....how to structure continuous reads of the serial ports. It's 9 bytes of data coming in at 100Hz from two ports 24/7. Could you suggest the best forum in which to post? Here somewhere, or perhaps stackexchange? I think here people will be more familiar with the Teensy 4.0's 4 byte buffer and how to make sure I keep it clear.

Thank You,
John

As far as Serial on two ports - that seems a valid forum topic for posting a thread - since this is your thread and project titled thread here is fine as well. With details the Teensy side can be detailed for use as needed. Like the T4 FIFO is 8 bytes - but included interrupt servicing code pulls that to a receive buffer of default size of 64 ( maybe 40 depending on the Serial#? ) Buffers can be increased easily as needed with core edit to handle more of a part second worth of incoming data. Then code just needs to keep those buffers clear to local sketch buffer for processing. serialEvent#() will do that on leaving loop each pass or when yield() { delay() } is called - or code can call a function to do that at will
 
Thanks Defragster.... Here's how I'm looking at this at the moment... Teensy 4.0 has 5 serial ports. It's a generic case..... suppose one wished to really use that capacity at 'high' data rates AND not lose data. The data is coming in completely asynchronously and continuously at some fixed rate.

Now in my specific case, It's coming in at 115200 on two ports in 9 byte chunks at 100 Hz. (But I may need to fiddle with the LIDARS and run them at say, 250 Hz.) So we have 8.6 uS per bit, say 12 bits per byte, 9 bytes per packet from the LIDAR, that's just under 1mS for the complete LIDAR reading to come in.

So, as I understand the UART IRQ functionality, these bits all come in to the uart without your code needing to know. i.e it's a high priority interrupt the user doesn't see or need to see. Then, when a byte does come in, SerialN.available becomes true. So, most projects can just put a check for if(SerialN.available == TRUE) in their main loop, then read in bytes until the uart FIFO buffer is empty. Which is fine for short, infrequent transmissions.

But the application here is for continuous 24/7 packets coming in at 100Hz without any lost bytes on multiple serial ports.

So, if say 4 bytes have come in on uart 1, and 2 bytes on uart 2, then really, there's not enough data to do anything with......you have to get in the whole 9 bytes then do a checksum before accepting the data.

So... it seems to me one would not want to poll Serial.available in the main loop, because that loop could indeed be doing quite a bit of computation. It seems to me a flag should be set by am ISR for each uart when 9 validated (checksum OK) bytes have been received in a program buffer. That flag would let the main program loop skip all the computation (hence loop faster) until there was some good validated data to process.

Geez, does that make sense I hope? I may be thinking wrong in my particular approach here, but it seems the generic problem of robustly pipelining continuous 24/7 data from multiple uarts is a good general problem. (This is where I wish I were a Computer Engineer, not an old EE!)

Thanks for thinking on this. I think understanding the solution will be useful to many Teensy users.

Regards,
John
 
… Opened editor and this file : ...\hardware\teensy\avr\cores\teensy4\HardwareSerial1.cpp
Has :: #define SERIAL1_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer

There are files with that setting for all the T_4 UARTS - each has 64 B Rx buffer. It is set up that you can directly edit that line to a larger size, or if you control the MAKE can set those things with a command line setting for that.

So perhaps setting that to 912 would work and hold a full second.

Unless you perfectly capture and wait for 100 or 250 messages per second - from one or two ports it will look like that - a continuous stream of bytes - already in the Rx buffer. Of course you wouldn't wait a full second - and whatever point the read is made - the last one is likely to be some part of the 9 byte message - to be held until the next set comes complete the message and the ones after that.

So 10 or 20 times a second - as desired - read all the SerialRx bytes to a local buffer and process them. Ideally you can identify the start and end and do the checksum to parse the stream into usable data and then do as desired.

Once that is running and the worst case time to empty the serial Rx buffer to local memory it might make sense to reduce the buffer size - but that probably not important loss of memory for the buffer it will give.

@tonton81 has a CircularBuffer library that should allow reading in all the current Rx bytes to local storage and then reading them out for processing.

That's the start as I'd make it. The time provessing that takes and the importance of other event and getting that data processed and passed on will determine in the end the order of focus and effort making it work - but that much would assure incoming LIDAR data won't be lost or currupted in the process.
 
Reply to defragster's post above.....

If I understand what you suggest then, I'd set an IRQ timer at say 50mS, and in the IRQ just quickly check SerialX.available and pull out of the serial buffer into the circular buffer. Sort of just While(SerialX.available){ CircBuffer[head] = SerialX.readread; head++}. Then do the same with a second circular buffer for the second serial port. In the main loop then, read out 9 byte chunks from the circular buffer, test checksum, and collect the distance data into a buffer for whatever the next processing step may be. Would just operate on the circular buffer
while(head-tail > 9){ read data to 9 byte buffer to validate checksum and extract distance data }
then the IRQ is let to run in the background filling the circular buffer.

Some error checking and validation work will be done servicing that circular buffer though.....i.e. checking for valid start bytes, then the checksum test, before taking out the distance bytes from the 9 byte packet. And, if that validation fails, will have to figure out how to recover the correct start and stop from the 9 byte packet before advancing the tail of the circular buffer. That's my next woe. ;)

I guess the thing I don't have totally clear is the IRQ priority between Serial.available and the 50ish mS timer IRQ. i.e. if I'm checking SerialX.available in the timer IRQ, and a byte comes in on the uart, the higher priority uart IRQ interrupts the timer interrupt, and when control is returned to the timer IRQ then it just has one more byte to process that wasn;t there when the timer IRQ fired. Yes? (I'm stretching here back to Z-80 days & hoping some things haven't changed!)

Thanks Again defragster, it's super helpful to have your review.
-John
 
Status
Not open for further replies.
Back
Top