wiringPi & wiringShift


19 posts
by Martwana » Sat Jan 19, 2013 9:44 pm
Anyone had any success in combining these two?

Trying to run a 16x2 through a shift register with wiringPi with no idea how to combine the two sets of functions.

All help appreciated :)
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by gordon@drogon.net » Sat Jan 19, 2013 10:03 pm
Martwana wrote:Anyone had any success in combining these two?

Trying to run a 16x2 through a shift register with wiringPi with no idea how to combine the two sets of functions.

All help appreciated :)


They work - but I would say that as I wrote it!

However one thing to be watchfull of is that the wiringShift library outputs data as fast as it can - which might have been OK for a C program on an ATmega, but on the Pi, it end up running the lines at about 10MHz...

A '595 shift register will work at this speed, but do keep the wires short and direct to start with.

I am experimenting with delaying it somewhat though.

So what you'll want to do is call wiringPiSetup (), then use pinMode() to set your pins to outputs (you'll need at least 3), then you can call shiftOut() with 8-bits of data then toggle the latch signal to the shift register to transfer to data into the output pins. If you are daisy-chaining shift registers with a common latch, then you need to call shiftOut() twice with the 2 x 8-bit values.

Just have a look at the source of wiringShift.c to see how it all works - it's really no more than calls to the existing digitalWrite() functions inside wiringPi.

Have fun!

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1541
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by Martwana » Sun Jan 20, 2013 4:40 pm
Thanks Gordon.

After looking at the lcd.c code, i can semi-understand it, but I need more help.

Read this and please correct me if you can.

In lcd.c, when initializing the lcd, in 4 bit mode 'func = LCD_FUNC | LCD_FUNC_DL', which according to the #defines is 0x20 and 0x10.
| is a bitwise OR, which when done is,
00100000 OR
00010000 =
00110000

The next line bitwise right shifts 00110000>>4 which i calculate as 00000011 ? Correct?

Now, if that is correct, 00000011 is sent to put4command, which takes rsPin low, then writes to each data pin.

It writes 'command & 1' which i calculate as
00000011 AND
00000001 =
00000001 correct?

Then, after doing each one, bitwise right shifts the 'command' which i think would change 00000001 to 10000000, 11000000 and 11100000. Correct?

I dont understand how to write these values out using shiftOut() because if I just ran the binary out to the shift register, it would send the binary to each pin of the register rather than sending it all to a specific pin.

I am totally new to C, so learning as I go, and I've never had any hardware interaction experience, before.
I CAN get the lcd working fine directly with the GPIO but I'm really struggling where to get started here.

Help me please.
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by gordon@drogon.net » Sun Jan 20, 2013 5:40 pm
Martwana wrote:Thanks Gordon.

After looking at the lcd.c code, i can semi-understand it, but I need more help.

Read this and please correct me if you can.

In lcd.c, when initializing the lcd, in 4 bit mode 'func = LCD_FUNC | LCD_FUNC_DL', which according to the #defines is 0x20 and 0x10.
| is a bitwise OR, which when done is,
00100000 OR
00010000 =
00110000

The next line bitwise right shifts 00110000>>4 which i calculate as 00000011 ? Correct?

Now, if that is correct, 00000011 is sent to put4command, which takes rsPin low, then writes to each data pin.

It writes 'command & 1' which i calculate as
00000011 AND
00000001 =
00000001 correct?

Then, after doing each one, bitwise right shifts the 'command' which i think would change 00000001 to 10000000, 11000000 and 11100000. Correct?

I dont understand how to write these values out using shiftOut() because if I just ran the binary out to the shift register, it would send the binary to each pin of the register rather than sending it all to a specific pin.

I am totally new to C, so learning as I go, and I've never had any hardware interaction experience, before.
I CAN get the lcd working fine directly with the GPIO but I'm really struggling where to get started here.

Help me please.


OK. First of all, I completely misunderstood when you said "run a 16x2" ... I thought this was some 16x2 LED array connected to the shift registers and not a 16x2 LCD display...

Now, going to the LCD code..

the code is put4command shifts to the right, so if we had 0011 to send, then

0011 & 1 = 1 - store in the pin
0011 >>=1 = 0001
0001 & 1 = 1 - store in the next pin
0001 >>=1 = 0000
0000 & 1 = 0 - store in the next pin
etc.

I'm now guessing that you have a single 8-bit shift register and are using it to talk to the display in 4-bit mode - with 4 pins on the shift register acting as the 4 data pins and one pin acting as the RS pin and another as the strobe (E) pin.

What you need to do is keep a software copy of the shift register and when you want to change one bit in the shift regsiter, you change it in your software copy, then clock the entire 8-bits into the shift register again.

If you wired it up so that the bottom 4 bits of the shift register were the 4 data bits, then it becoems easier.

So lets say you have a function:

writeDisplay ()

that function takes your saved byte (lets call it shadowValue) and calls shiftOut() then toggles the latch pin on the shift register.

the equivalent of put4command can be:

shadowValue = (shadowValue & 0xF0) | command ; // bottom 4 bits become command
shadowValue &= ~RS ; // Set RS to 0
writeDisplay () ;
shadowValue |= STROBE ; // Set STROBE pin to 1
writeDisplay () ;
shadowValue &= ~STROBE ; // Set STROBE pin to 0
writedisplay () ;

and then you can build everything else up from that.

The key is keeping a software copy (shadowValue) of the shift register, twiddling the bits in that copy, then sending that to the shift register. That way you can change a single bit at a time in the shift register.

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1541
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by Martwana » Mon Jan 21, 2013 5:39 pm
Cheers Gordon!

I'll work on it tonight, and let you know the outcome!

I'll likely post the code here if it goes bad anyway :)

Cheers again
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by Martwana » Mon Jan 21, 2013 11:25 pm
Gutter, my reply went missing.

I cannot get the code below to work, it wont even light up LED's.

Before the below code is executed, pinMode is set for each of the shift registers control pins.

I thought I had understood the code properly, but clearly not!

Where am I going wrong.

Code: Select all
writeDisplay(){


        // Set lcd pins on the register
        int d4 = 1;
        int d5 = 0;
        int d6 = 1;
        int d7 = 1;
        int e = 1;
        int rs = 1;

        // Put pins in array, with 2 extra blank values for the 2 unused pins on register
        int displayPins[8] = {d4, d5, d6, d7, e, rs, 0, 0};

        // SHIFT OUT TO REGISTER
        clear();

        // Convert the binary to a decimal value to shiftOut
        for (i=7;i>=0;--i){
                if (displayPins[i] == 1){
                digitalWrite(inputB, HIGH);
                } else {
                digitalWrite(inputB, LOW);
                }
                tick();
        }

delay(10000);

}


int main(){

        setupPins();
        writeDisplay();

}


Im lost, but I dont really want to give up.
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by rickseiden » Tue Jan 22, 2013 2:31 am
Here's my code for running an lcd display off a shift register. I hook the data pins of the lcd to the first four outputs of the shift registers, the register select pin to the fifth output, and the enable pin to the sixth output. That way enable is triggered only when everything else is already setup (more or less--it works, leave me alone!).

Code: Select all
#include <time.h>
#include <wiringPi.h>
#include <wiringShift.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int clockPin=14;  #23
int clearPin=10;  #24
int dataPin=11;   #26

int i;
int LCD_CHR=16;
int LCD_CMD=0;
int LCD_ENB=32;
int DELAY=500;
int LCD_LN1=0x80;
int LCD_LN2=0xC0;
int LEFT=0;
int CENTER=1;
int RIGHT=2;

void setup(){
        pinMode(clockPin,OUTPUT);
        pinMode(clearPin,OUTPUT);
        pinMode(dataPin,OUTPUT);
        digitalWrite(clearPin,HIGH);
        digitalWrite(clockPin,LOW);
        digitalWrite(dataPin,LOW);
}

void clear(){
        digitalWrite(clearPin,LOW);
        digitalWrite(clearPin,HIGH);
}

void lcd_byte(value,mode){
        int highBits=(value >>4)+mode+LCD_ENB;
        int lowBits=(value & 0xF)+mode+LCD_ENB;
        clear();
        usleep(DELAY);
        shiftOut(dataPin,clockPin,MSBFIRST,highBits);
        usleep(DELAY);
        clear();
        usleep(DELAY);
        shiftOut(dataPin,clockPin,MSBFIRST,lowBits);
        usleep(DELAY);
        clear();
        usleep(DELAY);

}

void lcd_init(){
        lcd_byte(0x33,LCD_CMD);
        lcd_byte(0x32,LCD_CMD);
        lcd_byte(0x28,LCD_CMD);
        lcd_byte(0x0C,LCD_CMD);
        lcd_byte(0x06,LCD_CMD);
        lcd_byte(0x01,LCD_CMD);
}

void lcd_string(char displayStr[50], int just){
        int extra=0;
        if (just==CENTER) {
                extra=(40-strlen(displayStr))/2;
        } else if (just==RIGHT) {
                extra=(40-strlen(displayStr));
        }
        for(i=1;i<=extra;i++){
                lcd_byte(32,LCD_CHR);
        }
        for(i=0;i<strlen(displayStr);i++){
                lcd_byte(displayStr[i],LCD_CHR);
                //printf("%d ",displayStr[i]);
        }
}
int main(){
        if (wiringPiSetup()==-1){
                exit(1);
        }

        char timeStr[40];

        setup();
        clear();
        lcd_init();

        time_t rawtime;
        struct tm * timeinfo;
        while (1==1){
                time(&rawtime);
                timeinfo=localtime(&rawtime);

                strftime(timeStr,40,"%I:%M:%S %p",timeinfo);

                lcd_byte(LCD_LN1,LCD_CMD);
                lcd_string(timeStr,CENTER);

                strftime(timeStr,40,"%B %d, %Y",timeinfo);

                lcd_byte(LCD_LN2,LCD_CMD);
                lcd_string(timeStr,CENTER);
        }
}
There are 10 types of people in this world. Those that understand binary, and those that don't.
Posts: 398
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA
by Martwana » Tue Jan 22, 2013 6:37 pm
rickseiden wrote:Here's my code for running an lcd display off a shift register. I hook the data pins of the lcd to the first four outputs of the shift registers, the register select pin to the fifth output, and the enable pin to the sixth output. That way enable is triggered only when everything else is already setup (more or less--it works, leave me alone!).

Code: Select all
#include <time.h>
#include <wiringPi.h>
#include <wiringShift.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int clockPin=14;  #23
int clearPin=10;  #24
int dataPin=11;   #26

int i;
int LCD_CHR=16;
int LCD_CMD=0;
int LCD_ENB=32;
int DELAY=500;
int LCD_LN1=0x80;
int LCD_LN2=0xC0;
int LEFT=0;
int CENTER=1;
int RIGHT=2;

void setup(){
        pinMode(clockPin,OUTPUT);
        pinMode(clearPin,OUTPUT);
        pinMode(dataPin,OUTPUT);
        digitalWrite(clearPin,HIGH);
        digitalWrite(clockPin,LOW);
        digitalWrite(dataPin,LOW);
}

void clear(){
        digitalWrite(clearPin,LOW);
        digitalWrite(clearPin,HIGH);
}

void lcd_byte(value,mode){
        int highBits=(value >>4)+mode+LCD_ENB;
        int lowBits=(value & 0xF)+mode+LCD_ENB;
        clear();
        usleep(DELAY);
        shiftOut(dataPin,clockPin,MSBFIRST,highBits);
        usleep(DELAY);
        clear();
        usleep(DELAY);
        shiftOut(dataPin,clockPin,MSBFIRST,lowBits);
        usleep(DELAY);
        clear();
        usleep(DELAY);

}

void lcd_init(){
        lcd_byte(0x33,LCD_CMD);
        lcd_byte(0x32,LCD_CMD);
        lcd_byte(0x28,LCD_CMD);
        lcd_byte(0x0C,LCD_CMD);
        lcd_byte(0x06,LCD_CMD);
        lcd_byte(0x01,LCD_CMD);
}

void lcd_string(char displayStr[50], int just){
        int extra=0;
        if (just==CENTER) {
                extra=(40-strlen(displayStr))/2;
        } else if (just==RIGHT) {
                extra=(40-strlen(displayStr));
        }
        for(i=1;i<=extra;i++){
                lcd_byte(32,LCD_CHR);
        }
        for(i=0;i<strlen(displayStr);i++){
                lcd_byte(displayStr[i],LCD_CHR);
                //printf("%d ",displayStr[i]);
        }
}
int main(){
        if (wiringPiSetup()==-1){
                exit(1);
        }

        char timeStr[40];

        setup();
        clear();
        lcd_init();

        time_t rawtime;
        struct tm * timeinfo;
        while (1==1){
                time(&rawtime);
                timeinfo=localtime(&rawtime);

                strftime(timeStr,40,"%I:%M:%S %p",timeinfo);

                lcd_byte(LCD_LN1,LCD_CMD);
                lcd_string(timeStr,CENTER);

                strftime(timeStr,40,"%B %d, %Y",timeinfo);

                lcd_byte(LCD_LN2,LCD_CMD);
                lcd_string(timeStr,CENTER);
        }
}


Did this code actually compile in C? I cant get it to work, it is out-putting characters, just in the most random order i have ever seen.

Did it work fine for you?
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by rickseiden » Tue Jan 22, 2013 6:47 pm
Worked fine for me. If I get a chance, I'll hook it up again tonight and double check.
There are 10 types of people in this world. Those that understand binary, and those that don't.
Posts: 398
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA
by Martwana » Tue Jan 22, 2013 7:02 pm
Im just fiddling about with your code just now, stripped out all the time stuff, just tying to print Hello, World! first, as you do :)

I added a tick function to tick the clock when using clear();

Code: Select all
tick(){
        digitalWrite(clockPin, HIGH);
        usleep(DELAY);
        digitalWrite(clockPin, LOW);
}


Still no joy though. Let me know how you get on with your rig.
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by rickseiden » Tue Jan 22, 2013 9:38 pm
The code doesn't compile because I used Python comments to indicate the GPIO physical pin numbers. The code should read:

Code: Select all
#include <time.h>
#include <wiringPi.h>
#include <wiringShift.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int clockPin=14;  //23
int clearPin=10;  //24
int dataPin=11;   //26

int i;
int LCD_CHR=16;
int LCD_CMD=0;
int LCD_ENB=32;
int DELAY=500;
int LCD_LN1=0x80;
int LCD_LN2=0xC0;
int LEFT=0;
int CENTER=1;
int RIGHT=2;

void setup(){
   pinMode(clockPin,OUTPUT);
   pinMode(clearPin,OUTPUT);
   pinMode(dataPin,OUTPUT);
   digitalWrite(clearPin,HIGH);
   digitalWrite(clockPin,LOW);
   digitalWrite(dataPin,LOW);
}

void clear(){
   digitalWrite(clearPin,LOW);
   digitalWrite(clearPin,HIGH);
}

void lcd_byte(value,mode){
   int highBits=(value >>4)+mode+LCD_ENB;
   int lowBits=(value & 0xF)+mode+LCD_ENB;
   clear();
   usleep(DELAY);
   shiftOut(dataPin,clockPin,MSBFIRST,highBits);
   usleep(DELAY);
   clear();
   usleep(DELAY);
   shiftOut(dataPin,clockPin,MSBFIRST,lowBits);
   usleep(DELAY);
   clear();
   usleep(DELAY);

}

void lcd_init(){
   lcd_byte(0x33,LCD_CMD);
   lcd_byte(0x32,LCD_CMD);
   lcd_byte(0x28,LCD_CMD);
   lcd_byte(0x0C,LCD_CMD);
   lcd_byte(0x06,LCD_CMD);
   lcd_byte(0x01,LCD_CMD);
}

void lcd_string(char displayStr[50], int just){
   int extra=0;
   if (just==CENTER) {
      extra=(40-strlen(displayStr))/2;
   } else if (just==RIGHT) {
      extra=(40-strlen(displayStr));
   }
   for(i=1;i<=extra;i++){
      lcd_byte(32,LCD_CHR);
   }
   for(i=0;i<strlen(displayStr);i++){
      lcd_byte(displayStr[i],LCD_CHR);
      //printf("%d ",displayStr[i]);
   }
}
int main(){
   if (wiringPiSetup()==-1){
      exit(1);
   }

   char timeStr[40];

   setup();
   clear();
   lcd_init();
      
   time_t rawtime;
   struct tm * timeinfo;
   while (1==1){
      lcd_byte(LCD_LN1,LCD_CMD);
      lcd_string("HELLO",LEFT);

      lcd_byte(LCD_LN2,LCD_CMD);
      lcd_string("WORLD!",RIGHT);
   }
}


I've also updated it to do just HELLO on one line and WORLD! on the other.

Save it to helloWolrd.c, then compile using

Code: Select all
gcc helloWorld.c -o helloWorld -L/usr/local/lib -lwiringpi
There are 10 types of people in this world. Those that understand binary, and those that don't.
Posts: 398
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA
by Martwana » Tue Jan 22, 2013 10:31 pm
rickseiden wrote:The code doesn't compile because I used Python comments to indicate the GPIO physical pin numbers. The code should read:

Code: Select all
#include <time.h>
#include <wiringPi.h>
#include <wiringShift.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int clockPin=14;  //23
int clearPin=10;  //24
int dataPin=11;   //26

int i;
int LCD_CHR=16;
int LCD_CMD=0;
int LCD_ENB=32;
int DELAY=500;
int LCD_LN1=0x80;
int LCD_LN2=0xC0;
int LEFT=0;
int CENTER=1;
int RIGHT=2;

void setup(){
   pinMode(clockPin,OUTPUT);
   pinMode(clearPin,OUTPUT);
   pinMode(dataPin,OUTPUT);
   digitalWrite(clearPin,HIGH);
   digitalWrite(clockPin,LOW);
   digitalWrite(dataPin,LOW);
}

void clear(){
   digitalWrite(clearPin,LOW);
   digitalWrite(clearPin,HIGH);
}

void lcd_byte(value,mode){
   int highBits=(value >>4)+mode+LCD_ENB;
   int lowBits=(value & 0xF)+mode+LCD_ENB;
   clear();
   usleep(DELAY);
   shiftOut(dataPin,clockPin,MSBFIRST,highBits);
   usleep(DELAY);
   clear();
   usleep(DELAY);
   shiftOut(dataPin,clockPin,MSBFIRST,lowBits);
   usleep(DELAY);
   clear();
   usleep(DELAY);

}

void lcd_init(){
   lcd_byte(0x33,LCD_CMD);
   lcd_byte(0x32,LCD_CMD);
   lcd_byte(0x28,LCD_CMD);
   lcd_byte(0x0C,LCD_CMD);
   lcd_byte(0x06,LCD_CMD);
   lcd_byte(0x01,LCD_CMD);
}

void lcd_string(char displayStr[50], int just){
   int extra=0;
   if (just==CENTER) {
      extra=(40-strlen(displayStr))/2;
   } else if (just==RIGHT) {
      extra=(40-strlen(displayStr));
   }
   for(i=1;i<=extra;i++){
      lcd_byte(32,LCD_CHR);
   }
   for(i=0;i<strlen(displayStr);i++){
      lcd_byte(displayStr[i],LCD_CHR);
      //printf("%d ",displayStr[i]);
   }
}
int main(){
   if (wiringPiSetup()==-1){
      exit(1);
   }

   char timeStr[40];

   setup();
   clear();
   lcd_init();
      
   time_t rawtime;
   struct tm * timeinfo;
   while (1==1){
      lcd_byte(LCD_LN1,LCD_CMD);
      lcd_string("HELLO",LEFT);

      lcd_byte(LCD_LN2,LCD_CMD);
      lcd_string("WORLD!",RIGHT);
   }
}


I've also updated it to do just HELLO on one line and WORLD! on the other.

Save it to helloWolrd.c, then compile using

Code: Select all
gcc helloWorld.c -o helloWorld -L/usr/local/lib -lwiringpi


I had already picked up on the comment issue, and i resolved it, but even that code doesnt work. it compiles fine (after changing the command to '-lwiringPi' but its still not printing the chars to the display.

It had loads of random symbols flashing on the screen.

Heres a video of it, any ideas?
http://www.youtube.com/watch?v=RzwllKSmu2I
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by rickseiden » Tue Jan 22, 2013 10:39 pm
Martwana wrote:It had loads of random symbols flashing on the screen.

Heres a video of it, any ideas?
http://www.youtube.com/watch?v=RzwllKSmu2I


Man! That's frustrating. Looks like the display isn't hooked up correctly, or the shift register isn't putting the bits out the way you expect them to. What I would do is hook up some LEDs to the outputs of the shift regsiter, then put a good 2 second pause after it sends each data set. Then you can see if what you think you should be getting out of the shift register is what you're actually getting.

Remember that the output of the shift register is D4, D5, D6, D7, RS, E. So the first output is hooked to D4 on the display, then the second to D5 and so on. My code does four bits instead of eight bits, so if you're still configured for 8 bit, that could be the problem, too.

If these hints don't get it working, post some pics of the circuit. Maybe I'll see something. Who knows.
There are 10 types of people in this world. Those that understand binary, and those that don't.
Posts: 398
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA
by Martwana » Tue Jan 22, 2013 11:50 pm
Nope :( Still no joy.

The leds all flicker as they run high and low.

Heres a few pics of the circuit, but i think its right. I've replaced the shift register since i ordered 3 but still no joy.

http://postimage.org/gallery/10tuftpi/f08ab16e/
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by rickseiden » Wed Jan 23, 2013 12:16 am
Martwana wrote:Nope :( Still no joy.

The leds all flicker as they run high and low.

Heres a few pics of the circuit, but i think its right. I've replaced the shift register since i ordered 3 but still no joy.

http://postimage.org/gallery/10tuftpi/f08ab16e/


I can't see what's wrong. My code calls for the wires to be connected to physical pins 24,25 and 26, but if your shift register is working, it looks like that's not it either. I've found, on occasion, that if I tear it down and start from scratch, it will work the second time around. Good luck!
There are 10 types of people in this world. Those that understand binary, and those that don't.
Posts: 398
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA
by Martwana » Wed Jan 23, 2013 12:20 am
I set the pins in the code correctly.

The photos you seen were like my 10th attempt at wiring it. is it maybe the type of shift register?

It's a 74HC164N register. I dont know if different kinds wont work with your code.

I have no idea where to go from here, I DID want to end up using the shift register to reduce the GPIO pins used for the display, since I was going to have another few devices hooked up, but maybe ill need to rethink it all.
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by rickseiden » Wed Jan 23, 2013 1:08 am
Martwana wrote:I set the pins in the code correctly.

The photos you seen were like my 10th attempt at wiring it. is it maybe the type of shift register?

It's a 74HC164N register. I dont know if different kinds wont work with your code.

I have no idea where to go from here, I DID want to end up using the shift register to reduce the GPIO pins used for the display, since I was going to have another few devices hooked up, but maybe ill need to rethink it all.


It looks like it's wired up right to me. The only thing I can think of at this point is that maybe you need to change MSBFIRST to LSBFIRST, but that's a long shot stab in the dark that probably won't work.
There are 10 types of people in this world. Those that understand binary, and those that don't.
Posts: 398
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA
by Martwana » Wed Jan 23, 2013 1:38 am
SOLVED.

This problem was solved using hardware AND software changes.
I was crawling about for any relation between the 74HC164N shift registers and the HD44780 displays. I wish I had the link, but I couldn't find it, but basically it mentioned that both the inputs on that register are ANDed together when data is shifted out to it. Someone in a comment had mentioned that they had experienced the display showing strange chars and by mistake he tied the second unused input high without noticing at first and he was able to get the output he desired. IF YOU READ THIS EVER CREDIT YOURSELF!

Anyway, I tied it high, straight onto the 5v rail and bingo, it works, but with loads of problems which I tweaked the code below to solve. In my case, I used the wire that would normally be used for Vcc for the register, as it seems to run fine without it.

Code is below with the changes below:

delay(1); - added to clear()
newShiftOut - exactly the same as wiringPi one with delay(1); in between the clock switching LOW then HIGH
References to 40 and 32 - in lcd_string(), the algorithm to calculate CENTER padding had 40 (40 character display) so was changed to 16. RIGHT algorithm was the same - changed to 16. The for loop below was altered from 32 to 16, which prevented funky characters appearing.
timeStr[] max size - reduced from 40 to 16 so there is no off screen chars. Finally on the last few lines where the time is generated, the values for the max size in strftime() is reduced again to 16 both times.

Note that I changed the date output format, and it is included in this code, but as you know easily changed.

Code: Select all
#include <time.h>
#include <wiringPi.h>
#include <wiringShift.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int clockPin=10;
int clearPin=11;
int dataPin=6;

int i;
int LCD_CHR=16;
int LCD_CMD=0;
int LCD_ENB=32;
int DELAY=1;
int LCD_LN1=0x80;
int LCD_LN2=0xC0;
int LEFT=0;
int CENTER=1;
int RIGHT=2;

void setup(){
        pinMode(clockPin,OUTPUT);
        pinMode(clearPin,OUTPUT);
        pinMode(dataPin,OUTPUT);
        digitalWrite(clearPin,HIGH);
        digitalWrite(clockPin,LOW);
        digitalWrite(dataPin,LOW);
}

void clear(){
        digitalWrite(clearPin,LOW);
        delay(1);
        digitalWrite(clearPin,HIGH);
}


newShiftOut(int dPin, int cPin, uint8_t val){
        int8_t i;

        for(i = 7; i >= 0; --i){
                digitalWrite(dPin, val & (1<<i));
                digitalWrite(cPin, HIGH);
                delay(1);
                digitalWrite(cPin, LOW);
        }
}

void lcd_init(){
        lcd_byte(0x33,LCD_CMD);
        lcd_byte(0x32,LCD_CMD);
        lcd_byte(0x28,LCD_CMD);
        lcd_byte(0x0C,LCD_CMD);
        lcd_byte(0x06,LCD_CMD);
        lcd_byte(0x01,LCD_CMD);
}

void lcd_string(char displayStr[32], int just){
        int extra=0;
        if (just==CENTER) {
                extra=(16-strlen(displayStr))/2;
        } else if (just==RIGHT) {
                extra=(16-strlen(displayStr));
        }
        for(i=1;i<=extra;i++){
                lcd_byte(16,LCD_CHR);
        }
        for(i=0;i<strlen(displayStr);i++){
                lcd_byte(displayStr[i],LCD_CHR);
                //printf("%d ",displayStr[i]);
        }
}
int main(){
        if (wiringPiSetup()==-1){
                exit(1);
        }

        char timeStr[16];

        setup();
        clear();
        lcd_init();

        time_t rawtime;
 struct tm * timeinfo;

        while (1==1){
                time(&rawtime);
                timeinfo=localtime(&rawtime);

                strftime(timeStr,16,"%H:%M:%S %p",timeinfo);

                lcd_byte(LCD_LN1,LCD_CMD);
                lcd_string(timeStr,CENTER);

                strftime(timeStr,16,"%x",timeinfo);

                lcd_byte(LCD_LN2,LCD_CMD);
                lcd_string(timeStr,CENTER);
        }
}



One last thanks to rickseiden for the original code and your help!
Posts: 30
Joined: Sun Dec 16, 2012 1:12 pm
by rickseiden » Wed Jan 23, 2013 1:49 am
Martwana wrote:SOLVED. ...
One last thanks to rickseiden for the original code and your help!


You're welcome. I'm glad you got it working.
There are 10 types of people in this world. Those that understand binary, and those that don't.
Posts: 398
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA