Serial interface to 7 segments

Hi There

I am a completely newbe with a Arduino, but I have a projekt I need some help with.
I have at timing software on a PC that are used to Streetrace and that gives me the time and speed on a serial port with this Protocol:

Protocol:
Byte No Byte Value (HEX) Description
1 FF Star Signs
2 0-1F Address decimal 0-31
3 AE Start data segments
4 See below 7 Segment sign
5 See below 7 Segment sign
6 See below 7 Segment sign
7 See below 7 Segment sign
8 0-FE Checksum 1
(9) 0-1 Checksum 2. Rarely used, see below
9 (possibly 10) FF Stop sign

Each 7 Segment sign built up of bits of a byte follows:

bit7 bit0

0, g segments, segment b, segment e, d segments, segments C, segment b, segment a

If for example. numeral 2 should be written thus becomes exchange value 01011011 in binary, which corresponds 5B hexadecimal.

I have now bought som 5x7 segments display, but the segments are not addressed individually, but with 4095 buffer/latch chips and they are just chained together.

so I think I need to convert the data from the PC to the display.

Is that something the Arduino can do and how will you approached this ??

Allan

Hi viper_dk,

That looks pretty feasible for an Arduino to handle.

I have now bought som 5x7 segments display, but the segments are not addressed individually, but with 4095 buffer/latch chips and they are just chained together.

Do you have the circuitry working? If you're not committed to this approach, you may want to consider something simpler like this:

Pat

Hi Pat

No I already got the display and the segments are 16,5" by 9,5"
and the diagram for the display is like this

Allan

TE 400mm display.pdf (11.9 KB)

and here are a picture of the segment

IMG_2547.JPG

Like patduino said it seems to be very easy to be done with Arduino. I don't know if you have some one working on this, if don't send me a PM.

Regards.

Yes, an arduino is a good way to do this.

I would start by writing some code that will drive the 7-segment display. I would build an object that looks like this:

SevenSeg {

  const byte dataPin;
  const byte clockPin;

  byte data[4]; // we have four 7-segment displays


  SevenSeg(byte attachData, byte attachClock) :
    dataPin(attachData),
    clockPin(attachClock)
  {
  }

  void setup() {
    pinMode(dataPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
  }

  void update() {
     // code goes here to send the correct chain of bits
     // to the 7-segment latches
     // hint: seer the 'shiftOut' function ion the standard library
  }
};


SevenSeg display(2, 3); // data pin 2, clock pin 3


void setup() {
  display.setup();
}

void loop() {
  static uint32_t mostrecentUpdateMs = 0;


  if(millis() != mostrecentUpdate) {
    mostrecentUpdate = millis();

    display.data[0] = mostrecentUpdate;
    display.data[1] = mostrecentUpdate>>8;
    display.data[2] = mostrecentUpdate>>16;
    display.data[3] = mostrecentUpdate>>24;

    display.update()
  }
}

Your goal is to fill out the update method to the point where you can see the segments at least lighting up.

From there, instead of just showing garbage on the segments, we'll alter it to make all the segments light up in sequence

  static uint32_t mostrecentUpdateMs = 0;
  static int currentBit = 0;


  if(millis() - mostrecentUpdate >= 500) {
    mostrecentUpdate = millis();

    currentBit = (currentBit+1) % 33;
    uint32_t bits = (0xFFFFFFFF) >> (32-currentBit);
    

    display.data[0] = bits;
    display.data[1] = bits>>8;
    display.data[2] = bits>>16;
    display.data[3] = bits>>24;

    display.update()
  }
}

This should make the segments light up in sequence - a to g. If they don't, then you'll need to tweak 'update' so that they do.

Once that's done, you can turn your attention to parsing the incoming data stream. The thing is, of course, that bytes come in one at a time. I tend, again, to make a parser object.

class ProtocolParser {
  byte data[4];

  void addByte(byte b) {} // add a byte to the frame
  boolean ready() {} // signals that a frame is complete
} parser;


void loop() {
  int ch = Serial.read();
  if(ch != -1) {
    parser.addByte((byte)ch);
    if(parser.ready()) {
      memcpy(display.data, parser.data, 4);
      display.update();
    }
  }
}

The job of the addByte method is to work out what to do when it gets a byte. This depend on how many it already has, of course.

It needs to watch for the stop bytes, pull out the data bytes and put them into the data array, and it should verify the checksum. If the checksum is ok, then it will set some internal 'ready' flag that stays set until it is given another byte. To do this, it needs some private internal variables that keep track of where in the frame it currently is.

parsing can be a complicated job, although if your connection is pretty reliable you could just go with counting.

Anyway. That's how I'd do it. The benefit of using a class for the parser is that it becomes much easier to test - feed in some bytes from an array that you build by hand to test it. Once it seems to work, turn it loose on the real data stream. If the parser is integrated into the body of your code, you have to do a fair bit of violence to things to do that. When it's encapsulated in a class, it's quite a bit easier.

And you can re-use your 'seven segment' class in other projects.