Pages: [1] 2   Go Down
Author Topic: LCD-7S04 Serial 7 Segment LCD Control  (Read 2495 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all,

This is my first posting, I hope I'm doing this right!

I recently bought this 7 Segment 4 digit LCD display (http://www.embeddedadventures.com/4_digit_7_segment_lcd_display_lcd-7s04.html), and am having a lot of trouble understanding how to get it to display what I want.  I have programmed a countdown timer and would like to display the time, but I am unsure how to get the time (unsigned long, converted to ints) to display on the LCD.  The site has a little tutorial in the datasheet, I hope one of you guys understand more than I do! 

Thanks a ton,
Nate
Logged

Israel
Offline Offline
Sr. Member
****
Karma: 5
Posts: 282
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I would recommend you use Arduino's SPI pins to connect the display. You'll need MOSI (pin11, data) and SCK (pin13, clock).
The datasheet mentions that all you have to do is shift in 5 bytes to update the display, and as you said they give a simple example. The display sections are active low, meaning that the bits you want to be lit should be 0s and the ones you need off should be 1s.
Please post what you are having a problem with exactly and we'll try to focus our help in that area.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey, thanks for the quick reply.  I don't actually understand the example, so it hasn't done me any good.  When you say shift in bits, what specifically does that look like in code?  I haven't used the spi pins before...  for example, if I want to display a 3 in the first digit, I need to light up sections 6 5 4 3 and 2 (I think). What should I send to the MOSI pin?
Logged

Israel
Offline Offline
Sr. Member
****
Karma: 5
Posts: 282
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You use SPI. There's an SPI library.
Basically you call SPI.begin() in the setup method and then SPI.transfer('your data byte') 5 times for each LCD section, where the first byte is the column.

By shifting-out what they mean is transfer the data. This LCD uses a serial connection, so each bit of a byte has to be "clocked in". Basically the data line is held at '1' or '0' and when the clock signal goes low (the datasheet says it reacts to clock-fall) the state of the data line registers as an input bit.
You probably just need to read a little bit on serial communication in general if you want to understand it better.

Here's a sample program I quickly came up with. I haven't tested it, didn't even compile it, but it should get you started.
Code:
#include <SPI.h>

                      //   0     1     2     3     4     5     6     7     8     9
const uint8_t nums[] = { 0xEE, 0x22, 0x7C, 0x76, 0xB2, 0xD6, 0xDE, 0x62, 0xFE, 0xF6 };
const uint8_t dot = 0x01;
bool column = true;
uint8_t display[5];

void setup()
{
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE2);
/*
At CPOL=1 the base value of the clock is one (inversion of CPOL=0)
For CPHA=0, data is captured on clock's falling edge and data is propagated on a rising edge.
Mode CPOL CPHA
0 0 0
1 0 1
2 1 0
3 1 1
*/
}

void loop()
{
// Display system uptime
display[0] = column ? 0xFF : 0x00; // if column = true then display[0] = 0xFF else display[0] = 0x00

uint16_t secs = millis() / 1000;
uint16_t mins = secs / 60;
secs %= 60;
display[1] = nums[(mins / 10) % 10]; // Tens of minutes
display[2] = nums[mins % 10];
display[3] = nums[(secs / 10) % 10]; // Tens of seconds
display[4] = nums[secs % 10];

for (uint8_t i = 0; i < 5; i++)
SPI.transfer(~display[i]);

// if you want to turn the dot on, you should use the following:
// SPI.transfer(~(display[i] | dot));
// ~ is a binary inverse. If your binary value is 00011010 its inverse will be 11100101, just as the datasheet requires.

column = !column;
delay(500);
}
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First of all, holy crap thanks a ton!  Just having some code with comments in front of me illuminated so much that many tutorials has not done, awesome. 

So I tried your code (it compiled, first try) and the display is just all on.  So I edited it as much as I felt comfortable, which was as follows

#include <SPI.h>

                      //   0     1     2     3     4     5     6     7     8     9
const uint8_t nums[] = { 0xEE, 0x22, 0x7C, 0x76, 0xB2, 0xD6, 0xDE, 0x62, 0xFE, 0xF6 };
const uint8_t dot = 0x01;
bool column = true;
uint8_t disp[5];

void setup()
{
   SPI.begin();   
   SPI.setBitOrder(MSBFIRST);
   SPI.setDataMode(SPI_MODE2);
        pinMode(13, OUTPUT);
   /*
      At CPOL=1 the base value of the clock is one (inversion of CPOL=0)
      For CPHA=0, data is captured on clock's falling edge and data is propagated on a rising edge.
      Mode    CPOL    CPHA
      0       0       0
      1       0       1
      2       1       0
      3       1       1
   */
}

void loop()
{
   // Display system uptime
   disp[0] = column ? 0xFF : 0x00; // if column = true then display[0] = 0xFF else display[0] = 0x00

   uint16_t secs = millis() / 1000;
   uint16_t mins = secs / 60;
   secs %= 60;
   disp[1] = nums[(mins / 10) % 10]; // Tens of minutes
   disp[2] = nums[mins % 10];
   disp[3] = nums[(secs / 10) % 10]; // Tens of seconds
   disp[4] = nums[secs % 10];

   for (uint8_t i = 0; i < 5; i++){
                digitalWrite(13, HIGH);
      SPI.transfer(~disp);
                digitalWrite(13, LOW);
                }
   // if you want to turn the dot on, you should use the following:
   // SPI.transfer(~(display | dot));
   // ~ is a binary inverse. If your binary value is 00011010 its inverse will be 11100101, just as the datasheet requires.

   column = !column;
   delay(500);
       
}


So I just added code to turn my clock line on/off to send a byte.  However, the display is still fully on.  I have tried the prgm using my "data" connected to pin 12, although I also tried 11 and 10 (I want MOSI, pin 11, right?  Or SPI pin 10?).  When connected to pin 10 the display turns fully off.

I really appreciate your help and tolerance of my coding ignorance, I am stoked to be learning something new though!
Logged

Israel
Offline Offline
Sr. Member
****
Karma: 5
Posts: 282
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You're welcome smiley

You don't have to change anything in the code, SPI is a hardware interface, you "tell" it to transmit a byte and it handles the data and clock lines on its own. Pin11 is the MOSI (Master Out Slave In) line, basically the data-out (out of the Arduino) line. Pin13 is the clock line, it toggles automatically as I already mentioned, so you don't have to manipulate any of the SPI pins yourself. Pin12 is the MISO (Master In Slave Out) pin, basically this is the data-in line, you only use it in case the devices you're "talking to" can transmit data back to the Arduino, this is not something your LCD can do, so you just leave it unused.
So the things you've added are not needed. One possible problem with the code is that the SPI settings transmits data at a rate of 4MHz by default. This might be too fast for the display.
- I would suggest trying to set SPI to the lowest speed possible (just to see whether it works) or not. Add this line after SPI.begin: SPI.setClockDivider(SPI_CLOCK_DIV128);
- If that doesn't help try to change SPI_MODE from 2 to the other options 0, 1, 3.
- In the case that fails, SPI might still be too fast for this particular display. In such a case you will probably have to implement your own function to "clock-in" the data yourself.
I think that the demo code in the datasheet is written in PIC specific C, but it shouldn't be very hard to adapt it to compile for the Arduino.
« Last Edit: August 19, 2013, 02:56:52 pm by TheCoolest » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried all your suggestions, no success.

Should I be using the shiftOut() command if I can't get the SPI library to work?  I still have yet to get a single comprehensible digit to show up on the display...  Are the bytes you put in the nums[] array what I should be using as data?

Also I've never worked with PIC, so I'm pretty confused by what they're doing in the example.  However if I can just get the damn thing to print even one digit that I want I think I'll be much better off in the direction of figuring this out!
Logged

Israel
Offline Offline
Sr. Member
****
Karma: 5
Posts: 282
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can try shiftout, in essence it simulates SPI in software, it might work.
If not I really can't tell you why it doesn't work for you. Do you get anything on the display? Do you see different shapes, changing every second? Does the colon blink?
I never worked with such a display before, so I can't really help you from past experience. I'm pretty sure that the values in nums should correspond with the values for each digit, you can confirm it yourself.
Also use Serial to print out the values to make sure I haven't made any mistakes in the code.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The display doesn't really do anything at all.  I can occasionally get it to move some stuff, but with no real consistency.  I have contacted Embedded Electronics, and they said they'd write a tutorial.  No guarantee on when that will be made though...

I'll keep plugging away, and if I sot anything out I'll let you know.  Thanks again!
Logged

Israel
Offline Offline
Sr. Member
****
Karma: 5
Posts: 282
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you post the diagram and a picture of how you connected the LCD to the Arduino?

Just in case I translated the 'shiftout' function included in the datasheet into Arduino C:
Code:
const uint8_t dataPin = 11;
const uint8_t clkPin = 13;

void ea_lcd7s04_write_data_byte(uint8_t data)

for( uint8_t count = 0 ; count < 8 ; count++ )
{
digitalWrite(dataPin, (data & 0x80));
data = data << 1;
digitalWrite(clkPin, LOW);
delayMicros(10);
digitalWrite(clkPin, HIGH);
}
}
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have spent a few minutes trying to figure out how to insert an image... no luck.  I haven't felt like such a noob in a good long while.

However, let me describe it to you in vivid detail.
The VDD is connected to 5V
The DI is connected to pin 11
The VSS is connected to GND
And the CLK is connected to 13

So in your ported code, would "data" be one array value in "nums" (e.g. ea_lcd7s04_write_data_byte(~nums[0]) ) ?  What does the & 0x80 do?  Your code using a digitalWrite instead of a shiftOut, is that preferable?
Logged

Israel
Offline Offline
Sr. Member
****
Karma: 5
Posts: 282
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well the connectivity seems to be correct.
To attach an image, simply click on "Additional Options" below the text box when you click on Reply.

This function is basically what shiftOut does. You can play with the delayMicros value, maybe increasing/decreasing it will have some effect.
And yes, you call it as just like you quoted.
I believe that SPI and shiftOut should both work, but when all fails you need to see if it's a problem with the code or maybe the display or the connections to the display. So I recommend giving this function a go to see what happens.
& is a logic AND, basically data & 0x80 will either return 0x80 or 0. Anything that isn't 0 is considered a HIGH, 0 is LOW, therefore when the most significant bit in data is '1' dataPin will be HIGH and when it's 0 dataPin will be LOW.
data = data << 1; shifts the bits in the variable left by one place, meaning that with every pass of the loop you're going through all the bits in 'data'.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay.

After playing around with this a bit, I have gotten this code.  All this does however, is make the screen do a disco dance party, turning segments on and off at what seems like random.  I must say this is better than before, but not by much.  Also, in the example code there is a bit of syntax that says data.7, what the .7 for?  Is it something important?

Code:

void setup()
{
                       //   0     1     2     3     4     5     6     7     8     9
//const uint8_t nums[] = { 0xEE, 0x22, 0x7C, 0x76, 0xB2, 0xD6, 0xDE, 0x62, 0xFE, 0xF6 };

pinMode(10, OUTPUT);
pinMode(12, OUTPUT);
digitalWrite(12,LOW);
}


void loop() {
byte nums[] = { 0xEE, 0x22, 0x7C, 0x76, 0xB2, 0xD6, 0xDE, 0x62, 0xFE, 0xF6 };

  ea_lcd7s04_write_data_byte(~(nums[0]));
  ea_lcd7s04_write_data_byte(~(nums[1]));
  ea_lcd7s04_write_data_byte(~(nums[2]));
  ea_lcd7s04_write_data_byte(~(nums[3]));
  delay(5000);
 
  }




void ea_lcd7s04_write_data_byte(byte data){
 
for( int count = 0 ; count < 8 ; count++ )
{
                digitalWrite(12, HIGH);
                digitalWrite(10, data & 0x80);
data = data << 1;
digitalWrite(12, LOW);
delay(200);

}
}

So this is basically your code, with the second half of the example code added.  I used 1234 as a target, seemed do able...  Anyway, let me know if you have any ideas why this might be acting so strangely.
Logged

Israel
Offline Offline
Sr. Member
****
Karma: 5
Posts: 282
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You forgot that you need to write 5 bytes to the LCD each time, the first being 0xFF or 0x00 for the colon section, you're currently writing only 4.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Progress!

I have gotten the display to display numbers, and have it mostly working.  Here's my code:

Code:

 
              //  0             1          2           3           4           5            6           7           8          9
byte nums[] = {0b11011101, 0b01000100, 0b11111000, 0b11101100, 0b01100101, 0b10101101, 0b10111101, 0b11000100, 0b11111101, 0b11100101 };
 
void setup()
{
// Set data as pin 10
pinMode(10, OUTPUT);

// Set CLK as pin 12
pinMode(12, OUTPUT);
digitalWrite(12,LOW);
}


void loop() {
    // turn on colon
  ea_lcd7s04_write_data_byte(0x00);
 
  // try to display 0 1 2 3
  ea_lcd7s04_write_data_byte(~(nums[0]));
  ea_lcd7s04_write_data_byte(~(nums[1]));
  ea_lcd7s04_write_data_byte(~(nums[2]));
  ea_lcd7s04_write_data_byte(~(nums[3]));
  delay(100);
 
  }




void ea_lcd7s04_write_data_byte(byte data){
  //data = byte(data);
for( int count = 0 ; count < 8 ; count++ )
{
                digitalWrite(12, HIGH);
                digitalWrite(10, data & 0x80);
data = data << 1;
                delayMicroseconds(100);
digitalWrite(12, LOW);


}
}

With this code I can display numbers. However, it seems like there is a bit getting bumped around.  So, if I display a zero (0b11011101) in my first digit, the last bit seems to get bumped into my 1 in the 2nd digits place.  See pic below.

I have to think this is some strangeness in my for() loop, but I can't seem to get an iteration that works. 

I would like to take this time to once again thank you for sticking with me, I hope you are getting some gratification out of this.  I'm learning a ton!



* 20130820_122459_Pearson Rd.jpg (1693.26 KB, 3264x2448 - viewed 56 times.)
Logged

Pages: [1] 2   Go Up
Jump to: