Page 1 of 1

Help getting a Noritake Itron VFD working on the ESP32

Posted: Wed Jun 27, 2018 5:42 pm
by davepl
The old Noritake Itron VFDs are beautiful, and I really want to make it work on my project. They're apparently a little nonstandard in that while they're supposed to work like a standard LCD, I could only get them to work with Noritake's demo code... and only on the Uno. So on the Uno with this code it works flawlessly, but I get no response at all on the ESP32.

The fact that it doesn't work at all on the ESP32 is either a problem with their interface code or my wiring. I'm using the following pins, and it's a DEVKITV1 NodeMCU32S.

Code: Select all

CUU_Parallel_I80_4bit interface(2, 18, 19, 21, 22, 23, 25); //RS,RW,E,D4-D7
They manually clock bits in and out, and on the AVR they use "delay.h" to get microsecond and millisecond delay functions. So my only change to the code was to define _delay_us and _delay_ms to use the ESP32 functions.

On the working AVR demo they delay for HALF a microsecond, which I don't think I can do, so I made it 1us instead. Perhaps that's the problem?

I'll post the interface code below, and if anyone has any suggestions on what my strategy should be here, please let me know!

Code: Select all

#define _delay_us(x) ets_delay_us(x)
#define _delay_ms(x) vTaskDelay(x)

#define MIN_US 1

class CUU_Parallel_I80 : public CUU_Interface {
protected:
    unsigned RS_PIN:4;
    unsigned WR_PIN:4;
    unsigned RD_PIN:4;
    unsigned D0_PIN:4;
    unsigned D1_PIN:4;
    unsigned D2_PIN:4;
    unsigned D3_PIN:4;
    unsigned D4_PIN:4;
    unsigned D5_PIN:4;
    unsigned D6_PIN:4;
    unsigned D7_PIN:4;

public:
    CUU_Parallel_I80(uint8_t rs, uint8_t wr, uint8_t rd,
      uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
      uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7):
        RS_PIN(rs), WR_PIN(wr), RD_PIN(rd),
        D0_PIN(d0), D1_PIN(d1), D2_PIN(d2), D3_PIN(d3),
        D4_PIN(d4), D5_PIN(d5), D6_PIN(d6), D7_PIN(d7)
    {
    }
    
    void init() {
        RAISE(WR);
        RAISE(RD);
        
        DIRECTION(RS, 1);
        DIRECTION(WR, 1);
        DIRECTION(RD, 1);
    
        DIRECTION(D0, 1);
        DIRECTION(D1, 1);
        DIRECTION(D2, 1);
        DIRECTION(D3, 1);
        DIRECTION(D4, 1);
        DIRECTION(D5, 1);
        DIRECTION(D6, 1);
        DIRECTION(D7, 1);
        
        write(0x30,false);  // 8-bit function set
    	write(0x30,false);  // 8-bit function set
    }
    void write(uint8_t data, bool rs) {
        SETPIN(D0, data & 0x01);
        SETPIN(D1, data & 0x02);
        SETPIN(D2, data & 0x04);
        SETPIN(D3, data & 0x08);
        SETPIN(D4, data & 0x10);
        SETPIN(D5, data & 0x20);
        SETPIN(D6, data & 0x40);
        SETPIN(D7, data & 0x80);
        
        SETPIN(RS, rs);
        LOWER(WR);
		_delay_us(MIN_US);// _delay_us(0.5);
        RAISE(WR);
    }
    uint8_t read(bool rs) {
        DIRECTION(D0, 0);
        DIRECTION(D1, 0);
        DIRECTION(D2, 0);
        DIRECTION(D3, 0);
        DIRECTION(D4, 0);
        DIRECTION(D5, 0);
        DIRECTION(D6, 0);
        DIRECTION(D7, 0);
        
        SETPIN(RS, rs);
        LOWER(RD);
        uint8_t data =
            CHECK(D7) << 7 |
            CHECK(D6) << 6 |
            CHECK(D5) << 5 |
            CHECK(D4) << 4 |
            CHECK(D3) << 3 |
            CHECK(D2) << 2 |
            CHECK(D1) << 1 |
            CHECK(D0);
        RAISE(RD);
        
        DIRECTION(D0, 1);
        DIRECTION(D1, 1);
        DIRECTION(D2, 1);
        DIRECTION(D3, 1);
        DIRECTION(D4, 1);
        DIRECTION(D5, 1);
        DIRECTION(D6, 1);
        DIRECTION(D7, 1);
        
        return data;
    }
    bool is8bit() { return true; }
};

class CUU_Parallel_I80_4bit : public CUU_Interface {
protected:
    unsigned RS_PIN:4;
    unsigned WR_PIN:4;
    unsigned RD_PIN:4;
    unsigned D4_PIN:4;
    unsigned D5_PIN:4;
    unsigned D6_PIN:4;
    unsigned D7_PIN:4;

public:
    CUU_Parallel_I80_4bit(uint8_t rs, uint8_t wr, uint8_t rd,
      uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7):
        RS_PIN(rs), WR_PIN(wr), RD_PIN(rd),
        D4_PIN(d4), D5_PIN(d5), D6_PIN(d6), D7_PIN(d7)
    {
    }
    
    void init() {
        RAISE(WR);
        RAISE(RD);
        
        DIRECTION(RS, 1);
        DIRECTION(WR, 1);
        DIRECTION(RD, 1);
    
        DIRECTION(D4, 1);
        DIRECTION(D5, 1);
        DIRECTION(D6, 1);
        DIRECTION(D7, 1);
        
        write(0x33,false);  // 8-bit function set, 8-bit function set
    	write(0x32,false);  // 8-bit function set, 4-bit function set
    }
    void write(uint8_t data, bool rs) {
        SETPIN(RS, rs);
        
        SETPIN(D4, data & 0x10);
        SETPIN(D5, data & 0x20);
        SETPIN(D6, data & 0x40);
        SETPIN(D7, data & 0x80);
        
		_delay_us(MIN_US);//_delay_us(0.5);
        LOWER(WR);
		_delay_us(MIN_US);//_delay_us(0.5);
        RAISE(WR);
		_delay_us(MIN_US);//_delay_us(0.5);
        
        SETPIN(D4, data & 0x01);
        SETPIN(D5, data & 0x02);
        SETPIN(D6, data & 0x04);
        SETPIN(D7, data & 0x08);
		_delay_us(MIN_US);//_delay_us(0.5);
        LOWER(WR);
		_delay_us(MIN_US);//_delay_us(0.5);
        RAISE(WR);
    }
    uint8_t read(bool rs) {
        DIRECTION(D4, 0);
        DIRECTION(D5, 0);
        DIRECTION(D6, 0);
        DIRECTION(D7, 0);
        
        SETPIN(RS, rs);
        LOWER(RD);
        uint8_t data =
            CHECK(D7) << 7 |
            CHECK(D6) << 6 |
            CHECK(D5) << 5 |
            CHECK(D4) << 4;
        RAISE(RD);
        
        _delay_ms(1);
        
        LOWER(RD);
        data |=
            CHECK(D7) << 3 |
            CHECK(D6) << 2 |
            CHECK(D5) << 1 |
            CHECK(D4);
        RAISE(RD);
        
        DIRECTION(D4, 1);
        DIRECTION(D5, 1);
        DIRECTION(D6, 1);
        DIRECTION(D7, 1);
        
        return data;
    }
    bool is8bit() { return false; }
};

...and here's the CUUInterface file...

#include "Arduino.h"
#include <stdint.h>

//#define _delay_us(us) ets_delay_us(us)
//#define _delay_ms(ms) vTaskDelay(ms)

#define DIRECTION(X,D)  if (D) pinMode(X##_PIN, OUTPUT); else pinMode(X##_PIN, INPUT)
#define RAISE(X)	digitalWrite(X##_PIN, HIGH)
#define LOWER(X)	digitalWrite(X##_PIN, LOW)
#define CHECK(X)	digitalRead(X##_PIN)
#define SETPIN(X,V) digitalWrite(X##_PIN, (V)? HIGH: LOW)

class CUU_Interface {

public:
    virtual void init() = 0;
    virtual void write(uint8_t data, bool rs) = 0;
    virtual uint8_t read(bool rs) = 0;
    virtual bool is8bit() = 0;
};
#include "Arduino.h"
#include <stdint.h>

//#define _delay_us(us) ets_delay_us(us)
//#define _delay_ms(ms) vTaskDelay(ms)

#define DIRECTION(X,D)  if (D) pinMode(X##_PIN, OUTPUT); else pinMode(X##_PIN, INPUT)
#define RAISE(X)	digitalWrite(X##_PIN, HIGH)
#define LOWER(X)	digitalWrite(X##_PIN, LOW)
#define CHECK(X)	digitalRead(X##_PIN)
#define SETPIN(X,V) digitalWrite(X##_PIN, (V)? HIGH: LOW)

class CUU_Interface {

public:
    virtual void init() = 0;
    virtual void write(uint8_t data, bool rs) = 0;
    virtual uint8_t read(bool rs) = 0;
    virtual bool is8bit() = 0;
};


Re: Help getting a Noritake Itron VFD working on the ESP32

Posted: Thu Jun 28, 2018 4:00 am
by ESP_Sprite
One thing to check: is the VFD okay with taking the 3.3V signals the ESP32 spits out, as opposed to the 5V signals of the Uno?

Re: Help getting a Noritake Itron VFD working on the ESP32

Posted: Thu Jun 28, 2018 3:16 pm
by davepl
I tried a logic level converter on the data lines as a whim, but noticed from the data sheet that a logic high input is Vss+2.2V so I figure the ESP32, at 3.3v, should be able to meet that. But I'm a noob and could be way wrong.

Re: Help getting a Noritake Itron VFD working on the ESP32

Posted: Thu Jun 28, 2018 5:21 pm
by mikemoy
I agree with ESP_Sprite, as that is the first thing to check.
Correct me if I am wrong, but I think your ms delay is wrong.
I think it should be:

Code: Select all

#define _delay_ms(x)   vTaskDelay( x / portTICK_PERIOD_MS )

Re: Help getting a Noritake Itron VFD working on the ESP32

Posted: Fri Jun 29, 2018 11:46 am
by ESP_Sprite
Also note that vTaskDelay can be unreliable for values close to the 1/(freertos tick rate).