using an HV5812 with arduino - Page 1
Forum section: electronics / general

author: jordan_me160
author_rank: Contributor
timestamp: April 28, 2019, 03:12:11 pm
content: I am sort of new to arduino and am building a counter of sorts with a VFD screen (IV-21 if it matters) and going to use an arduino to do all the maths and data then use a HV5812 to actually drive the display (both grids and segments).my only roadblock so far is i cant figure out for the life of me what to actually code in the arduino to push that data out to the display. Ive already done a ton of googling and found a demo code for this chip for an arduino but when i load it up it throws compiler errors on just about every line.I also cant seem to wrap my head around using an ASCII table to lookup the binary code of a given number then turn that into the segment pins on the HV5812 along with grid and whether i should be using SPI to control it or treat it as any other shift register and just use a data, clock and latch (assuming this chip uses strobe as latch) pins.if someone could help me at least get 1 digit of the 8 on my display working then move to multiplexing the rest the help would greatly be apreciated and if there are still questions that i have not answered i will do my best to answer them as quickly as i can

author: Ian.M
author_rank: Super Contributor
timestamp: April 30, 2019, 01:20:47 am
content: IV-21 is an eight digit, seven segment (+d.p.) VFD, with a leading circle dot or minus symbol extra 'digit'.It cant display ASCII, only numbers 0 - 9 (or if you don't mind a fugly mix of upper and lower case hexadecimal numbers 0 - F).You'll need a 7 segment 'font' table (const array, in program memory) storing the segments to illuminate for each possible digit. Thw contents of the 'font' table depends on the bit order of the segments in the byte which depends on how you wire the IV-21 to the HV5812.The HV5812 has a very simple SPI-like interface - data is clocked in on the rising edge of CLK and transferred to the outputs on the rising edge of STROBE, very much like driving a string of 74HC595 SIPO shift registers. I did a breadboarded Arduino based 4 digit VFD clock using 2x 74HC595 shift registers + ULN2803 drivers for the logic level to VFD signal level interface a while back, and my code should be fairly easy to convert for a HV5812: just add four more bytes to the display buffer, extend the multiplexing to 9 digits (8 + leading symbols), and output an extra byte via SPI for each digit of the multiplexing to handle the extra four output pins of the HV5812.Code and Schematic here:https://www.eevblog.com/forum/projects/vacuum-fluorescent-display-multiplexing-problem/msg1041506/#msg1041506

author: floobydust
author_rank: Super Contributor
timestamp: April 30, 2019, 03:39:49 am
content: Consider looking at the"Ice Tube Clock"which uses an IV-18 andMAX6921serial HV driver, 20 output. It's similar to the HV5812, or MicrochipHV518.I think theIV-21VFD is the same except for 8 digits vs 9 with the IV-18.The Adafruit kit version was not so great, there were issues and then it got abandoned.The P-ch mosfet switching the tube's filament power ended up giving low voltage to the heaters which was a huge PITA.It uses the MEGA328 MCU to generate the boost-converter 31kHz but it's open-loop, no regulation.Also uses the MCU as the real-time clock, so it drifted a bit too much and ate batteries when on them.There are a few different firmware loads out there. People upgraded to a decent RTC or GPS, and better dimmer etc.Source code is open, maybe look athttps://github.com/johngarchie/xmas-icetube; mods for HV5812 would not be too difficult in display.cThe cheap plastic case was too light, with tension of 5V power cord it slid off the desk and smashed the tube into pieces. I have a replacement but the clock was just not worthy of more time.If you're going to have fun doing this project, do it right with a decent RTC and enclosure.

author: jordan_me160
author_rank: Contributor
timestamp: April 30, 2019, 01:03:53 pm
content: Quote from: Ian.M on April 30, 2019, 01:20:47 amfirst off thanks for the help, as for the font table if you can show me an example of how it should be done that would be verry helpful (i am wiring it so grids go from HVout1 to grid 1 HVout2 to grid 2 and so on to grid 9 being HVout9 and then segments being A-G with A being HVout10, B HVout11, C HVout12 and so on with g being HVout16)i had a look through the code and forgive if im a bit dense and dumb int his area but i couldnt find the display buffer in the code, would it have to be part of my own code i am writing and id just modify yours/rewrite it to make it work in mine?

author: Ian.M
author_rank: Super Contributor
timestamp: April 30, 2019, 02:34:24 pm
content: I'm afraid my code uses a lot of macros etc. to try to make it as general purpose as possible. In theory one just edits VFD.H to accommodate differing hardware. However I never tested it with more than 5 digit grids and i know it need real code changes to handle more than eight digit grids.Quote from: jordan_me160 on April 30, 2019, 01:03:53 pmThe 'font' table is defined as the array VFDfont[] near the top of VFD_drv.cpp. The SCRAMBLE() macro (defined in VFD.h) is used if the physical segment anode wiring isn't in the standard order abcdefg with g as the LSB, to rearrange the 'font' segment bit patterns to match the physical wiring. a commented out example SCRAMBLE() is given for reverse (gfedcba, a as LSB) seg. order. You *NEVER* need to change the patterns in the binary numbers in font table definition you just change the SCRAMBLE() macro which rearranges them when the sketch is compiled to get them into a bit order that matches your hardware.QuoteIn VFD.h the digit mapping is set by a comma separated list of which bit in the byte or word to use for each digit grid bit.Code:#define VFD_DIGMAP 0b0001, 0b0010, 0b0100, 0b1000 //Alter digit mapping and total number hereIn VFD_drv.cpp that digit mapping list is used to declare a const array digbit[] used, with a digit index to scan through the digits in the multiplexing. The size of digbit is used to set a const for the number of digits, and that is then used to define the display buffer VFDdispBuff[].Code:static const unsigned char digbit[]={VFD_DIGMAP}; //Digit select mappingconst unsigned char VFDdigits=sizeof(digbit);volatile unsigned char VFDdispBuff[sizeof(digbit)];Therefore, for up to eight digits one only has to change the number of entries in the list VFD_DIGMAP in VFD.h, and the sizes of all the other arrays including the display buffer VFDdispBuff[] follows automatically. Over eight digits you also need to rearrange what is sent by SPI.transfer() in the multiplexing timer interrupt in VFD_drv.cpp to add another byte for the extra digit grid lines required for more than eight digit grids, and would need to make VFDdigits[] unsigned integer.

author: jordan_me160
author_rank: Contributor
timestamp: May 02, 2019, 01:02:45 pm
content: hello, sorry for taking this long to replay its hard to find time to work on this project when working full time too.anyways i made the changes to the codeCode:#define VFD_DIGMAP 0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000, 0b01000000, 0b10000000 //Alter digit mapping and total number hereis this correct?i also went and connected everything up, said f-it and sent it to my arduino on the breadboard and the screen lit up but was only displaying either 8 across all digits and flashing the decimal with the segment all flashing very fast but not fast enough for it to be clearly an 8, or just flashing random segments across the screen. is there something else ive done wrong or missing? and sorry for seeming fairly inept with this it gets hard to focus and figure things out after working a full day already.

author: NivagSwerdna
author_rank: Super Contributor
timestamp: May 02, 2019, 01:27:28 pm
content: I use HV5812s and also multiplex which makes things a bit more complex. Because of the multiplexing I actually do all display updates by being timer driven... your solution might be simplier?Anyway my low level routines are...Code:inline void pulseClock() {PORTB &= B11111110;PORTB |= B00000001;}inline void strobeLow() {PORTB &= B11111011;}inline void pulseStrobe() {PORTB |= B00000100;PORTB &= B11111011;}inline void outputData(boolean isSet) {if (isSet) {PORTB |= B00000010;} else{PORTB &= B11111101;}}void blank() {strobeLow();outputData(true);for (int i = 40 + 1; i != 0; i--) {pulseClock();}pulseStrobe();}void outputPattern() {// Send out a patternstrobeLow();for (int i = 0; i <= 4; i++) {byte b = patternBits;for (int j = 0; j < 8; j++) {boolean isClear = b & B00000001;b >>= 1;outputData(!isClear);pulseClock();}}pulseStrobe();}[I use two HV5812s in a daisy chain so have to squirt 40 bits (8x5) before pulseStrobe to finish.]Obviously your hardware will determine which bits to twiddle. In my hardware it looks like CLK, DATA and STROBE are RB0, RB1, RB2 respectively... which I think are D8, D9, D10 in UNO speak.If you post a partial schematic you might get more info.

author: Ian.M
author_rank: Super Contributor
timestamp: May 02, 2019, 01:33:11 pm
content: Quote from: jordan_me160 on May 02, 2019, 01:02:45 pmThat's a good start. However as the HV5812 has 20 outputs, it needs three bytes sent to it by SPI.transfer() in the ISR, not the two my code uses. The extra four bits in the first byte shift right through it so are effectively discarded unless you daisy-chain multiple HV5812 chips.In VFD_drv.c, try:Code:// send in the address and value via SPI:#ifdef VFD_INVERTEDSPI.transfer16(~digbit);SPI.transfer(~VFDdispBuff);#elseSPI.transfer16(digbit);SPI.transfer(VFDdispBuff);#endifN.B. digbit will be sent first as two bytes so its lower 12 bits will end up on outputs HVout9 - HVout20, which go to the digit grids. VFDdispBuff will be sent as a single byte and ends up on outputs HVout1 - HVout8, which go to the segment anodes.Alternatively if you don't want to rewire it from your reply#3 wiring, try:Code:// send in the address and value via SPI:#ifdef VFD_INVERTEDSPI.transfer16(~(VFDdispBuff<<1));SPI.transfer(~digbit);#elseSPI.transfer16(VFDdispBuff<<1);SPI.transfer(digbit);#endifbut it would be a PITA controlling HVout9 for the 9th (symbol) digit, as its mixed in the same byte as segments A-F. It *can* be done but it makes the code more complex so IMHO its preferable to rewire.P.S. If you are keeping the reply #3 wiring, to get the correct segment bit order I *THINK* you'll also need to swap the VFD_SCRAMBLE #defines in VFD.h by commenting out the normal order one and uncommenting the reverse order one.

author: jordan_me160
author_rank: Contributor
timestamp: May 02, 2019, 01:40:56 pm
content: Thanks fir the help i will try this once i get home and re-wire the display the way you describe it as i currently have it wired the oposite way so the grids go HVout1-9(8 because i wont use the 9th dash/dot this time to make it a bit simpler)and then the segments would be HVout9-16.

author: jordan_me160
author_rank: Contributor
timestamp: May 03, 2019, 01:05:27 pm
content: i have done everything listed, changed the code more and rewired it, when i got home yesterday...i also figured out the rapid segment spamming, my strobe pin was connected to the wrong pin on my arduino so it wasn't getting a signal. however with all that fixed its still not showing all segments, it seems to by count up 1-9 but its displaying the same number on all digits and for some reason some digits are missing segment but once it switched to another number the segments turn on for that number. unfortunately the picture ive taken of what its doing is too big for the site so i cant show you what its doing.

author: Ian.M
author_rank: Super Contributor
timestamp: May 03, 2019, 10:51:33 pm
content: All I can suggest is you post your current sketch (zipped, with all the .h and cpp files - the Arduino IDE will make the zip file for you, with everything needed inside it, if you do Tools: Archive Sketch), and a schematic. You can also probably find somewhere else to post the video (e.g. youtube) and link to it.Meanwhile here are a couple of suggestions to slow it right down to aid debugging:In VFD.h just below the VFD_DIGMAP #define, you'll find:Code://#define VFD_MUXRATE 1 //N interrupts per digituncomment it and change it toCode://#define VFD_MUXRATE 255 //N interrupts per digitand it will slow down the multiplexing by a factor of 256 for testing. i.e each digit grid will be on for about 1/4 second.Also, my sketch may be running the SPI to the HV5812 too fast. Also in VFD.h change:Code:#define VFD_SPI_SET 15000000, MSBFIRST, SPI_MODE0 // MODE 0, as fast as possibletoCode:#define VFD_SPI_SET 100000, MSBFIRST, SPI_MODE0 // MODE 0, at 100KHz

author: jordan_me160
author_rank: Contributor
timestamp: May 05, 2019, 08:51:57 pm
content: sorry for taking so long with this reply but here is the schematic and the packaged arduino sketch as for the schematic the battery and buck/boost converters are there because i don't actually have a power supply with multiple outputs yet.i will put a link to a video on you tube of what its doing once i can actually record it and upload itedit**upon looking at the schematic again i noticed pin 9 on the arduino should go to pin 13 on the HV5812 with arduino pin 8 should be pin 10 and go to pin13 on the HV5912**

author: jordan_me160
author_rank: Contributor
timestamp: May 09, 2019, 01:06:36 pm
content: hello, sorry for taking a week to get this done but here is the link to the youtube video of my display, as stated in the description the first 53 seconds are at muxrate of 2 and the rest of the video is at muxrate 254, to show both sides of whats its doing because i honestly do quite understand the problem. i get how its multiplexing it but i don't get why its not working.https://youtu.be/yQfuJb-16SI

author: NivagSwerdna
author_rank: Super Contributor
timestamp: May 09, 2019, 01:42:10 pm
content: I read the code and didn't like itthe HV5812 can be driven at 5Mhz so you can bit-bang it at full speed... (see example above) and get rid of all that horrible SPI Arduino Wiring plumbing.The underlying SPI hardware has I believe a one byte buffer and then clocks out at a lower 'SPI' speed with interrupt and buffering magic in between... I would never call such gunk from inside an interrupt.

author: Ian.M
author_rank: Super Contributor
timestamp: May 09, 2019, 02:26:13 pm
content: @NivagSwerdna,In ArduinoLand one does Arduinoish things and use Arduino libraries. e.g. use the 'Wiring' SPI wrapper, even in ISRs. If you also code on more 'bare iron' MCU platforms, the overheads involved and code stench from the libraries will no doubt cause offence, but that's the price you pay for easy portability across the Arduino range and compatibles.@jordan_me160: Sorry I didn't have time to look at what you posted earlier this week. I hope to fit it in over the next day or so. Topic bookmarked.

author: Ian.M
author_rank: Super Contributor
timestamp: May 09, 2019, 04:27:07 pm
content: I see one potential problem immediately, which could explain why unwanted segments and digits are illuminating. You seem to be running the filament from a 2.6V output buck converter, and I suspect you have one end of the filament grounded. However most VFDs need negative grid bias to get full cutoff (digit not illuminated), and as your HV5812 can only pull the grids down to 0V, you need the filament cathode to have a positive voltage as a whole. Ideally it should be run on AC with a center tapped filament transformer with the cathode bias voltage applied to the center tap, but you may be able to get away with a beefy 5.1V zener diode in series with the ground end of the filament then readjusting the buck converter for approx. 7.7V out to get 2.6V across the filament.Noritake'sA Guide to Fundamental VFD Operationis a *MUST* *READ*. Pay particular attention to sections 5 & 6.

author: jordan_me160
author_rank: Contributor
timestamp: May 09, 2019, 06:33:57 pm
content: I will have a look at the page you linked once i get home this evening and if i don't have a zener diode closely matching the one described order some on digikey (im lucky last order i made i got in about a day or 2). As for the screen its self i mentioned in my first post this is going to be a counter of sorts but its counting decimals, ie: 1.2345678 with the decimal staying after the first (from the left) digit. And as for the code you provided i looked through and couldnt find where the clock part of the code stores a variable that the vfd code reads and turnes into the segment/digit code. I was wondering where it is or rather how id go about changing it for my purpose.

author: NivagSwerdna
author_rank: Super Contributor
timestamp: May 09, 2019, 07:13:06 pm
content: The wonderful thing about this forum is it shows you how little you know! Very interesting since I have only Nixie experience and these VFDs are very different.There is a very interesting thread here...https://www.eevblog.com/forum/projects/showing-my-vfd-psu/msg1610392/#msg1610392Which I might use as a basis for some play if I ever find the time.