Translate

Showing posts with label ESP32. Show all posts
Showing posts with label ESP32. Show all posts

Saturday, 19 March 2022

Garmin HUD & ESP 32 stand-alone module.

A couple of years ago I upgraded my mobile phone, and was dismayed to find Garmin no longer supported my much-beloved HUD (Heads up display), rendering it redundant. It was only 7 years old at the time... is that acceptable product life expectancy? Gutted. 

I seem to remember reading somewhere that the same display was built into BWM cars ... are BMW owners in the same situation?

It featured in my Mini speedo video here. 

Thankfully, someone had reverse engineered the bluetooth serial protocol used to control the device. 

The original work was carried out by gabonator (here), Frank Huebenthal and subsequently by skyforcetw (here). Stunning work. Skyforcetw had even written an android app to interface Google maps to the Garmin HUD, excellent. Except nothing I could do would persuade it to run. 

So I tried skyforcetw's arduino library, and attempted to load it into an ESP32, and tried to modify it for SerialBT. After a lot of debugging and chopping of code from Frank Huebenthal's work, I finally started to get some meaningful information displayed on the HUD. 

So, after this success, a plan was hatched. I just want some meaningful info displayed. I'm not particularly interested (nor capable of) writing something for my phone to run , so I'm thinking about a simple speed display, and maybe some other info.. 

So a UBlox GPS module (this one's an M7, but it will work fine with the cheaper M6)  is hooked up to the ESP32's Serial 2 port on pins 16 & 17, and to the 3V3 and GND pins. 
I recycled my sketch from way back, which was used to configure the GPS receiver in run-time (you can, therefore, use the slightly cheaper module without the battery) and then set about working out why I couldn't get the GarminHud library to run. It turns out that SerialBT's write command isn't quite implemented correctly, so I modified the SendHud function to utilise print instead, which worked.

Version 2 of gabinator and Frank Huebenthal library features a "Down" arrow, which would allow me to implement a GPS compass using the direction arrow function. A gps clock is implemented, a speedometer (in mph, but easily changed to Km/h or knots should the need arise)  and a display of the number of satellites in view (and a warning of no GPS lock) 
There's a slight issue when drawing an "up" arrow. Whatever is written next to the direction display is ignored! This slight bug is overcome by simply writing anything other than "up" twice! 

The sketch (and the required GPS library) can be found on my github here.

The unit is mounted in a box, along with a simple 7805 power supply, and trialled. 

Here's a video of the unit in action. 


... another saved from landfill! 

Sunday, 16 January 2022

ESP32 Big Filament YouTube Subscriber counter

Now I've made a couple of new YouTube videos (one's not quite published as yet) I thought I might like one of those counters, that people have in their videos... Techmoan has one... 

It would seem sensible to utilise the big filament clock display... 

So there's some different code at https://github.com/andydoswell/filamentclock... 

There's no change to the hardware.


If I ever get to 10,000... I'll need another digit.


Friday, 31 December 2021

ESP32 Big filament clock

Inspired by one of Big Clive's YouTube videos (see here), I fancied doing something with the LED "filaments" you can get from AliExpress. 

I fancy making a big 7-segment display clock. 

Some where duly ordered up, and arrived some time later.








Now they need around 47V to light... and (allegedly) 30mA , but experiments show they are more than bright enough at 3.3mA for our purposes...

So, let's make a clock display!

Problem no 1: The power supply. 

Unlike Clive, I'm not going to run the clock off rectified mains ... I did contemplate a capacitive dropper, but, again, it's not safe. 

A quick dig about in the junque box did provide a couple of suitable transformers... one with 18-0-18 and one with 15-0-15, with 220V primaries. As we are normally somewhat above 220V here, and the secondary will very lightly loaded, these would probably do, and some tests are run. Getting an low voltage output to run the micro will mean another transformer ...

The I though about using one of the ebay buck-boost modules... except for they top out at 35V .... or do they?

Now the module is based on the LM2577_ADJ. Shown here in it's boost configuration. R1 on the module is a 10K multi-turn pot, and R2 is a fixed 360 ohm resistor.  
The output voltage is controlled by the feedback pin, so that the feedback pin is always at 1.2V. The module differs from the schematic shown here, as it has two inductors to allow for buck and boost operation, but the voltage feedback section remains the same.

 A quick calculation shows that making that resistor 250 ohms would give us an output voltage of 50V. The existing R1 is removed... 
... and replaced with a 220 ohm resistor soldered to the rear. 220 ohms will allow us some adjustment. 


The output capacitor is removed, as it's only got a 35V rating.


... it's replaced with a 100uF 63V part.


The module is powered up and adjusted for 50V
And a filament is tested. The unit is being powered from 5V, useful, as I can power the whole thing from a 5V wall wart. 








To keep power consumption down a bit, I'm going to multiplex the display. It also reduces the wiring somewhat. Each of the 4 digits of the clock will have it's own anode supply, with only one digit ever lit at a time. This allows us to connect each of the segment's cathodes together. 

The anodes will require a high-side drive, that will happily hold off our 50V. After looking around in the transistor box, it looks like a 2N7000 will do. It's a 60V FET. We'll need two per drive. I've got a load of them, and they're cheap. 


The micro's 3.3V high signal comes in via the 10K resistor, and switches on the lower 2N7000. This removes the gate signal from the upper 2N7000, and removes the anode's supply. The two resistors (100K and 47K) are there as a potential divider, so we do not exceed the maximum gate-to-source voltage of 20V. We'll need to remember the logic is inversed, input of high turns the output low, but we can sort this in software. 

It's built up and tested on a breadboard. 
For the cathode drive, we can use our old friend the ULN2003 (just, it's rated to a maximum of 50V... we could have used individual transistors again, say the 2N7000... anything rated to 50V would have done) 




The micro's inputs come into pins 1-7 and the output to each cathode via it's own 1K current limiting resistor. 

Excellent.

We'll use the ESP32, as we can utilise it's Wifi to get the current time via NTP, and it has it's own RTC. It's proved excellent in the ESP32 analogue clock. 

The end schematic is rather simple. I've added switches for wifi reset (more about that later) and 12/24 hours, and an output to drive the colon separator between the hours and minutes.

I did contemplate a PCB... but it's quite simple, so it's implemented on a piece of perfboard.








So, how to mount the filaments? 

Fusion 360 is fired up, and a design created. 



It's just a bit too large for my 3D printer, but it should be OK... 







I did have to scale it slightly to fit on my Anycubic Mega S, a friend of mine has a Pursia, and he rekons it'll fit on that if this works out too small. Anyway, it's printed, and sanded back to get rid of any lines, and painted with a little high-build primer. 



and finally finished in a bit of satin black. 








The LEDs are tested on the bench supply, some are intermittently faulty, or just dead.









Each filament gets a couple of wires soldered to each end, and threaded into the back... 








Much tea later ... 











The filaments are quite fragile, and I lost a few along the way... 


A couple of warm white LEDs are inserted to form the colon, and everything sealed into place with a dab of RTV. 








The whole thing is wired up ... each digit's anodes are connected together, and each segments cathodes are connected together..

What a rats nest !




The software owes a lot to the ESP32 analogue clock from earlier in the year. It still uses NTP to acquire the time, and uses the ESP's in built RTC. The new parts are a software multiplexer for the display... it goes like this....

1. All anodes off.
2. Set cathodes.
3. Switch on one anode.

... and repeat until the display is complete. It's identical in principle to the display driver for the STD305D turntable The ESP32 is more than capable of doing this faster than the eye can make out (in fact, it's capable of doing it FASTER than circuitry can switch the LEDs on, so there's a delay in the programme to slow it down!), so it just looks like the whole display is lit. 

The other nice bit about the software is the use of the WiFiManager library, which gives us an easy way to connect to wifi without all that tedious hard coding. That's also why I've provided a reset button, which erases the WiFi credentials, and resets the unit, so you can add a new SSID, if yours changes or you move the clock to another location with a different SSID.

Power consumption of the running clock is a bit over 250mA 


The software, as usual can be found on my git, along with the 3D model for the back panel. 



WiFi Manager in use ...



Just for fun, I did run one of the filaments at 30mA just to see what would happen... 

It was incredibly bright ... and lasted for about 30 mins before starting to flicker, eventually going open circuit after another 20 minutes. 

Sunday, 21 March 2021

The ESP32 Analog (Analogue!) Clock

As promised, here's the new stupid analogue clock. 

It consists of two 270 degree analogue meters, thoughtfully calibrated 0-70V and 0-300A, kindly donated by Andy from North Hill Audio in Malvern, and an ESP32 with it's nice in-built RTC, wifi etc etc...

The idea is almost identical to the previously stupid analogue clock, found here. This time, we will use the ESP32's built in wifi to connect to the internet, and pick up the time from an NTP server, and set the ESP32's inbuilt RTC. There's an example in the ESP32's arduino library to do this, and utilises the standard time.h library to maintain the clock. I'll set a random time to refresh the RTC randomly between 12 and 24 hours, I don't want to keep bothering the NTP server. I can then output hours and minutes using PWM to drive the meter movements. 

First off we're going to need to do something about the scaling on our meter movements, as I can't easily drive 0-70 volts, nor 0-300 amps! 

Examining the meters shows the 0-300A meter is actually a 75mV full scale deflection meter (FSD), designed to be used with an external shunt of 0.025 ohms (or does it ... read on), this is good, as we can easily drive that.

The 0-70 volt meter reads directly. Disassembling it shows it has a "multiplier" resistor (actually 3 resistors in series, one adjustable) with the earthy end of the movement. 









Shorting out the multiplier gives us a meter with about 200mV FSD, perfect. The meters are dated 1972.
Both meters pull a fair amount of current ... 

A schematic is conjured up. There's not much too it.

As ESP32 has no native support for analogWrite, but we can use the ledc function. I don't care it's not driving an LED, and neither should you 😉. Each output pin, feeds the base of BC547 NPN transistor which is driving the meter. There's a 1K pot in the emitter to allow FSD for the meters to be set accurately. The venerable 7805 regulator supplies our +5V to the ESP32 and meters. 

There's an output on IO18 for a PM indicator LED, and an output on IO15, which I'm going to use to drive a relay, to give the clock a ticking sound ...

The script has some differences to the original ATMEGA328P script, as there's no 409Hz interrupt timing required, as the RTC is doing that job for us, and the code to receive the 433MHz timing signal has now gone, as that's now taken over by NTP. There's a section to extract the individual hours, minutes and seconds from the RTC, and load them into separate variables that we can manipulate. There's also no "smooth" function, as both hours and minutes are smooth, and there's no 400Hz interrupt timer to give us 1/409th of a second to drive a "smooth" seconds meter, and there isn't one anyway! The clock is also permanently set to 12 hour mode, with a PM indicator on pin XX. I've retained the fabulous "IsBST" routine. It just works. If you're outside of the UK, you'll need to modify the code to suit your timezone.

The software can be found on my github page at https://github.com/andydoswell/ESP_32_analogue_clock

The electronics is mounted up on perf board.











So that's the electronics and software sorted. 

I ordered a wooden craft box from eBay to mount it all in.













A couple of stains and finishing oil are tried out on the inside... 











.. and while they dry, I use libre cad to make a cutting plan for the front. 












The template is printed out , and taped to the box.












The two holes are cut out for the meters












The box given many coats of finishing oil to bring out the grain, and give it some shine.

I had to get a bit creative when  mounting the meters, as I didn't have the original mounting hardware..












I added some redundant 19" rack handles as a stand. I'm pleased with the results.

There, and goodnight, it's 250 amps past 51 volts!








I notice there's a kickstarter, where you can now buy something very similar. 





Pyers read this last night, and has pointed out the value of the shunt is wrong. I simply glanced at the back of the 300A meter, and mis-read it... I had wrongly assumed 0.025ohms was the value of the shunt... But 75mV across 0.025 ohms only gives us 3A... not 300.
Reading the label correctly, it simply states "Use with external shunt" , and the 0.025ohms is "lead resistance". The shunt should be 0.00025 ohms for a full scale deflection of 300A. 

Thursday, 25 February 2021

Moving on up from ATMEGA328 & Arduino. The ESP32 "Mexican wave" light chaser.

I've recently been looking at other microcontroller options for some upcoming projects. Arduino and the ATMEGA328 have been wonderful devices, but it's getting on a bit now. 

I've played with the very powerful Teensy range of controllers a little bit, and they're great, just, well, a bit pricey .... The audio functions they perform are, however, wonderful. Probably great "bang for the buck" ... I just really don't need that much bang!

A while ago, I visited the USA, and one guy there gave me a "Blue Pill" , a fast, 32 bit microcontroller, with plenty of IO. Sadly not much in the way of RAM, and support for libraries seems a bit lacking. It is, however, stupid cheap.

I seen & read a bit on the ESP32. Looks good, and is cheaply priced. I've bought a couple. The one thing that (sort of) lets it down is the absence of a simple analogWrite function to control it's myriad of PWM outputs. It does have 2 proper DAC's though. Thankfully there's a function called ledc, which is largely similar, but operates at a higher (5KHz) PWM frequency than Arduino uno (nano etc) 490Hz, which makes filtration a bit easier. It's got wifi, bluetooth, a magnetic hall sensor (why??), and a built in RTC, and probably much more!

A while back I built the Arduino analogue clock , and always intended  to incorporate two large 270 degree meters. I never got round to it. My intention is to modify the code to use the in-built RTC, synchronised by NTP via Wifi, and use that to drive the meters. Seems easy enough, and will be a good project to cut my teeth on. 

In the meantime, I've been playing with ledc to make a mexican-wave style LED chaser, to get the hang of things a bit. It's based on adding more channels to the example supplied in the Arduino IDE for ESP32.

Hang some LED's off the pins as listed in the code, with appropriate current limiting resistors (220Ohm), and enjoy.




/*
  LEDC Software Mexican wave
  
*/

// use first 8 channels of 16 channels
#define LEDC_CHANNEL_0     0
#define LEDC_CHANNEL_1     1
#define LEDC_CHANNEL_2     2
#define LEDC_CHANNEL_3     3
#define LEDC_CHANNEL_4     4
#define LEDC_CHANNEL_5     5
#define LEDC_CHANNEL_6     6
#define LEDC_CHANNEL_7     7


// use 13 bit precission for LEDC timer
#define LEDC_TIMER_13_BIT  13

// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ     5000

// fade LED PIN (replace with LED_BUILTIN constant for built-in LED)
#define LED_PIN_0      23
#define LED_PIN_1      22
#define LED_PIN_2      21
#define LED_PIN_3      19
#define LED_PIN_4      18
#define LED_PIN_5      17
#define LED_PIN_6      16
#define LED_PIN_7      15

int brightness [] = {0, 32, 64, 96, 128, 160, 192, 244, 255}; // how bright the LED is

int fadeAmount[] = {1,1,1,1,1,1,1,1}; // how many points to fade the LED by

// Arduino like analogWrite
// value has to be between 0 and valueMax
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
  // calculate duty, 8191 from 2 ^ 13 - 1
  uint32_t duty = (8191 / valueMax) * min(value, valueMax);

  // write duty to LEDC
  ledcWrite(channel, duty);
}

void setup() {
  // Setup timer and attach timer to a led pin
  ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_0, LEDC_CHANNEL_0);
  ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_1, LEDC_CHANNEL_1);
  ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_2, LEDC_CHANNEL_2);
  ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_3, LEDC_CHANNEL_3);
  ledcSetup(LEDC_CHANNEL_4, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_4, LEDC_CHANNEL_4);
  ledcSetup(LEDC_CHANNEL_5, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_5, LEDC_CHANNEL_5);
  ledcSetup(LEDC_CHANNEL_6, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_6, LEDC_CHANNEL_6);
  ledcSetup(LEDC_CHANNEL_7, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN_7, LEDC_CHANNEL_7);
}

void loop() {

  for (int i = 0; i <= 7; i++) {
    ledcAnalogWrite(i, brightness[i]); // set the brightness of each led in the array
    brightness[i] = brightness[i] + fadeAmount[i]; // increase the brightness of each led
    if (brightness[i] <= 0 || brightness[i] >= 255) { // until it gets to 255, then reverse the direction of fade, until it gets to 0, and reverse again
      fadeAmount[i] = -fadeAmount [i];
    }
    delay (1);
  }
}