Close

IT FLIPS !!!

A project log for Flip-Dot Display & DIY Controller

Messing around with Annax Flip-Dot displays.

Frederic LFrederic L 08/19/2018 at 07:102 Comments

Today I earned the dot flipper badge, and a milestone in this project has been reached. Those few weeks of hard work, figuring all out, selecting components, designing a PCB and coding a simple firmware finally paid off !

Below is my very first dot flipped, and you cannot imagine how excited I was when I heard the clicking sound after plugging in the power supply. More tests shown below.


I kept the code as simple as possible :

#include <Arduino.h>
#include <SPI.h>  // Using SPI is faster than bit-banging in that case

// SPI pins for sending data into shift registers
#define SPI_SPEED 8000000  // 8 Mhz
#define PIN_CS_ROW 22
#define PIN_CS_COL 21
#define PIN_RST_ROW 2
#define PIN_RST_COL 0

// Pins used for flipping dots
#define PIN_SET_RESET 4
#define PIN_PULSE 15

// Fixed parameters
#define PULSE_LENGTH_US 200  // May be adjusted according to voltage used
#define SET 1  // HIGH
#define RESET 0  // LOW


void clear_registers() {
  // Resets shift registers
  digitalWrite(PIN_RST_ROW, LOW);
  digitalWrite(PIN_RST_COL, LOW);
  delayMicroseconds(1);
  digitalWrite(PIN_RST_ROW, HIGH);
  digitalWrite(PIN_RST_COL, HIGH);
}


void load_single_dot(uint8_t x, uint8_t y){

    // Clear shift register data
    clear_registers();

    // Initialise SPI communication
    SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE0));

    // Transmit coordinate x and y coordinates to shift registers :

    // Slave Select Columns shift registers
    digitalWrite (PIN_CS_COL, LOW);
    SPI.transfer(1 << (x%8));
    for(int i=0; i<(x/8); i++){
      // Insert 8 blank bits 'spacers' if x>=8
      SPI.transfer(0x00);
    }
    digitalWrite (PIN_CS_COL, HIGH);

    // Slave Select Rows shift registers
    digitalWrite (PIN_CS_ROW, LOW);
    // 16 rows, so let's send all 16 bits at once, it's overall faster.
    SPI.transfer16(1 << y);
    digitalWrite (PIN_CS_ROW, HIGH);

    // End SPI
    SPI.endTransaction();

}

void flip(bool dir) {
  // SET or RESET mode
  digitalWrite(PIN_SET_RESET, dir);
  delayMicroseconds(1);

  // Send pulse
  digitalWrite(PIN_PULSE, HIGH);
  delayMicroseconds(PULSE_LENGTH_US);
  digitalWrite(PIN_PULSE, LOW);
}


void setup() {

  // Defining outputs
  pinMode(PIN_CS_ROW, OUTPUT);
  pinMode(PIN_CS_COL, OUTPUT);
  pinMode(PIN_RST_ROW, OUTPUT);
  pinMode(PIN_RST_COL, OUTPUT);
  pinMode(PIN_SET_RESET, OUTPUT);
  pinMode(PIN_PULSE, OUTPUT);

  // Initial outputs state
  digitalWrite(PIN_SET_RESET, LOW);
  digitalWrite(PIN_PULSE, LOW);

  // Clear Shift Registers
  clear_registers();

  SPI.begin();

}


void loop() {

  // Load (x,y) coordinates of dot to flip
  load_single_dot(0, 0);

  flip(SET);  // YELLOW
  delay(2000);
  flip(RESET);  // BLACK
  delay(2000);

}

I eyeballed the pulse length to 200us for a start, thinking I would have to increase it to a higher value, but it seems to work perfectly and I might even be able to reduce it a touch. It would increase the overall frame rate, as waiting for the pulses to complete is the most time consuming task of the process (loading the shift registers takes on average 20us per dot).

Anyway, here is what I got flipping each dot every 200ms, and finally at full speed without any delay.

I’m quite impressed, knowing this is only the very first tests and a lot of optimisation is possible ! Stay tuned, while I hypnotise myself looking at it. 


BONUS VIDEOS :

Discussions

Harry wrote 08/22/2018 at 01:22 point

WoW... great work Fred! 

Great to see what you have achieved with the Annax flip-dot modules....

  Are you sure? yes | no

Yann Guidon / YGDES wrote 08/21/2018 at 01:11 point

That's so awesome !!!

Congrats !!!

  Are you sure? yes | no