I decided it was time for another blog post now things are a little quiet due to the global pandemic and am rather shocked to have seen that 5 months has disappeared somewhere! How on earth is this possible?? So what have I done in 5 months? Well rather a lot which I'm quite proud of - it's amazing looking back at these posts and seeing the learning process; things I thought were deeply impressive feats which now seem quite trivial - I'm sure this progress will seem trivial in 5 months too; right now it seems like I've cracked the enigma code though...
So last time around I was just getting into Autodesk Eagle and making my first board design. I originally wanted to have a pair of Teensy 3.2 microcontrollers to run the dash, but soon realised that I wanted to also have the capacity to read the various switches and control the various LED indicators from the TVR OEM switchpacks. This required individual control of around 30 LEDs, plus PWM control of several more instrument cluster backlight LEDs via some mosfet amplifiers. The 3.2 board simply didn't have enough outputs to manage this task, so I added a 3.5 to the mix:
![]() |
Teensy 3.5 Microcontroller |
Adding this board found me running into a problem with Eagle - even with the paid version, there is a limit on the overall board space that can be used, and while I forget exactly what the limit is, it is not big enough to house all 3 microcontrollers, together with the servos and other hardware required. Together with the fact that I already needed an offset board for one of the servos that I was staggering to bring the motor hubs as close together as possible, this now mandated that I needed at least one more PCB design. In actual fact I needed 3 more; one each side for the backlighting LEDs that I wanted to keep as far away from the decal to be lit as possible (to allow the light to diffuse and give an even effect). After lots and lots of trial & error I ended up with this working design:
4 Boards Laid Out in Inventor |
Rear View |
I think I probably mentioned this in the last blog, but this presented quite a challenge - mostly due to flipping between two different design viewpoints in two different software packages. I would start in Eagle; working on the schematics to solve the electrical problem of running the wiring and components such that the system world work as intended, which then translated into the board design trying to fit the components onto the boards I wanted in as small a space as possible. I would then use Eagle to generate a .step file of the board (a clever feature!) and import this into Inventor where I could manipulate the boards into my housing assembly and see whether they would fit in the space and allow clearance for the servos, for the LED light to correctly reach the intended parts that needed lighting and so on. Then of course there was the challenge of creating some mounting points to hold the boards in place, board offsets, connector access, the list goes on!
After several iterations of this loop, once I had a decent idea of the components and their proposed locations, I decided to draw the board out in Inventor to the exact shape I wanted, with mounting holes. I then exported the outline of this solid as a .dxf drawing, which could be imported into Eagle as a drawing layer which I could then replace the board outline. This allowed me to be much more accurate with my shapes and mounting points, giving me confidence that I could place my components anywhere within the designated space. After some time, I arrived at the following design:
![]() |
Rear PCB Schematic |
![]() |
Front PCB Schematic |
![]() |
Rear PCB - 4 Layer Design |
![]() |
Front PCB Design |
I was pretty pleased by this point, though was a little concerned with the rear PCB design - you might note that there are 4 copper layers on that board. At the time I was using some quite large spacing for the vias and holes which resulted in me not being able to compile the board using only 2 layers - the computer simply couldn't route everything together with only two planes to play with, no matter how I laid out the board (and I tried a lot of combinations!).
Hoping for the best, I contacted PCBCart.com and went for my first round of quotations and learned very quickly that my 4 board idea wasn't going to work - for me at least. The cost of doing this dramatically increased the manufacturing complexity and tolerances became much tighter, rocketing the price over £1000 for this board alone. Back to the drawing board!
After scratching my head some more, I enlisted the help of some kind fellows on the Arduino.cc forum to see if they could help me compile my board and spot any glaring errors. I was educated on the rules around spacing vias and holes and traces, and learned some good practice of filling in the unused space with grounded copper to help reduce any electrical noise. After some more fiddling, I arrived at a more acceptable 2 layer version. My wallet sang!
![]() |
Rear PCB - 2 Layer Version |
In the process of doing this, I also started breadboard testing more of the functions, and did lots of reading on input conditioning - ensuring that my potentially noisy electrical signals in my car wouldn't fry the inputs of my Teensy boards. I introduced voltage dividers and opto couplers on inputs, level shifters on outputs to beef up my control signals, and added diodes and to prevent reverse current. Confident that my design was now robust, I tried a second go at the quotation period and moved into the manufacturing phase.
PCBCart.com were fantastic to deal with, very friendly, accommodating and generally patient with me as a complete electronics novice. After reviewing my Eagle generated manufacturing files, they spotted some errors in my bill of materials (BOM) with incorrectly placed components or components they couldn't source - mostly with suggestions where they could. I realised I hadn't really thought about the BOM (terrible coming from an engineering background!) and thought (incorrectly) that the manufacturer would source "suitable" components to fill the slots. They do not, and sent me back to go through my BOMs line by line, in each case to select the exact part number for every resistor, diode, chip and capacitor. Weirdly I quite enjoyed it, though it did in some cases make me realise that I didn't understand some of what I was trying to do, and forced me to go back and understand the fragments of circuits that I'd plagiarised. This exercise helped fix a few errors to boot!
A sample of the working BOM for one PCB |
Some time later, I received one of the most satisfying mail deliveries of my life - it felt like christmas (and actually wasn't too long after christmas either!):
![]() |
New Toys! |
![]() |
Assembled Together |
![]() |
With Teensy 3.2s & 3.5 fitted in their sockets |
I will never forget how scared I was plugging these into the the power supply first time. Expecting to see smoke/flames/worse. I am actually amazed that these worked as well as they did given they were essentially prototype #1. I had lofty hopes of getting them dead on first time, so set about testing each and every function, one pin at a time, which meant programming each Teensy to ping each pin and see if the right signal came out of the other end.This took a very long time (most of that 5 months I suspect!) but I was trying so hard not to blow anything up in the process...
It was actually the first time I had tried really running more than 1 motor together, plus the screen and it revealed a huge amount of work that I needed to do on my code, so as I slowly worked though each function, I was having to write the code almost from scratch, and constantly test that each new piece wasn't interfering with any other piece of code. I think the hardest thing was getting the stepper motors to play ball. My old problem of a slugglish response reared its head with vengeance! Once I added the full function list and tried to run it all together the inefficiency in my code showed badly:
I stuck at it, and after a lot of fiddling I ended up with at least a hope that I could make it work in time. This was a pretty big milestone:
Knowing that I could control the 4 servos and the OLED screen were a huge relief - at least my prototype would work well enough to do some development. I decided that I'd come far enough to warrant 3D printing the housing to see how it fit together, and whether my juggling of Inventor and Eagle had worked out. So I sent through my models for the front and rear housing, decal and spacer, and a couple of days later received this little beauty:
![]() |
Prototype 3D Printed Housing |
This actually worked surprisingly well too - it fits together nicely, the mounting points work perfectly, but I decided the decal was a little too far recessed into the unit so on the next version I'll reduce the front lip to bring the decal closer to the front of the unit. With a little more programming and testing we soon ended up with a lighting test:
Might need to turn them down a bit! Thankfully I built in PWM control on the 4 different lighting sets (front board LEDs, Rear Case LEDs, Servo Hub LEDs and Dashboard External LED control) so I can tune them to an appropriate level and then have a global pot input to then be able to turn dim the lot in unison when in the car. You'll note that the steppers here are still very jittery. In my attempt to speed up the response, I ran the processors faster than normal and began calling the steppers with quite aggressive settings using Accelstepper, an Arduino stepper motor library. No matter how much I fiddled with this, I could never get it to work very well.
Coupled to this, I also realised that my input was not going to be a 0-5v potentiometer as I had been using. An offshoot project was born to be able to simulate a 5v square wave pulse for both the speed sensor (a toothed wheel on the gearbox) and the RPM signal (from the ECU). Since I wanted the dash to work equally well using CAN bus data or analogue signals, I first had to simulate these signals, then try to read them. I ended up using a spare Teensy 3.2 as a signal generator, linked to some pots to enable me to control the simulated wheel speed and engine RPM pulse frequency.
![]() |
My Test Rig with pots to control fuel level, water temp, RPM & speed, lights on/off, ignition on/off, menu function and my Teensy 3.2 frequency generator. |
Reading pulsed inputs presented me with a host of new challenges. It turns out that if you want to read a pulsed input, you need to know exactly when the pulse arrives, down to the nanosecond when working at this frequency. It actually takes time for the code to execute each cycle, so if a pulse comes in while the Teensy is running another piece of code then you need to know. This required the use of software interrupts. My poor tiny mind was blown once again. Getting this right took some time and a lot of perseverance to successfully read signals for both the RPM and the speed signal, while also running the CAN bus OBD scanning code to look for the fuel and temperature signals I was simulating using another Arduino based CAN simulator (from a previous post). Also running a serial data service to share numbers between the display board and the motor board, and the lights board, and the display its self, the list goes on... Getting this working harmoniously took some doing, but the Teensys were now busy, and my stepper motor code suffered further. Accelstepper wasn't going to work.
After a lot of research, I had a little luck. It turned out that someone had had a similar stepper problem to my own, and had written their own stepper controller library for specifically Teensy boards called TeensyStep. It was leaner, faster and smarter than Accelstepper, and looked to be exactly what I was after. Sadly it came with no manual, and my application was a little different to the typical use case for the library. No bother - I was close and like a dog with a bone by this point, so I pushed on with testing and failing several times until a crack of light appeared, and finally some silky smooth steppers working in harmony with the full code. Another HUGE sigh of relief and a well earned beer.
I made a thing!
Comments
Post a Comment