RobG 1,892 Posted July 23, 2011 Share Posted July 23, 2011 Here you can find header and asm files and the link to LCD post. kenemon 1 Quote Link to post Share on other sites
kenemon 29 Posted July 24, 2011 Author Share Posted July 24, 2011 Sorry to bother again Rob, How difficult would it be to have your code work with the HD44780, forgoing the serial board for simplicity, and having a contained LP sensor/display shield? Thanks. KB -Always thinking, sometimes clearly Quote Link to post Share on other sites
RobG 1,892 Posted July 24, 2011 Share Posted July 24, 2011 Serial board is used to save pins, you need 6 or 10 to control HD44780. LP has 10 available pins so after 2 or 4 used for the encoder, you have enough to control LCD in 4bit mode (6 pins.) kenemon 1 Quote Link to post Share on other sites
kenemon 29 Posted July 24, 2011 Author Share Posted July 24, 2011 Hey Zeke, as I grope through this new sensor, I am able to get your code to work for me. A little bounce, which i can deal with later. What do you think about porting the LED bits to the HD44780. How hard is it to estimate 8 positions and TX that output to the RX of the same chip to have a graphic output on the LCD? Edit: sorry Rob, I did not see your post. What about using a larger chip such as the 453 or 553 for more pins? the uart project from a couple weeks ago only uses 1 port KB Quote Link to post Share on other sites
RobG 1,892 Posted July 24, 2011 Share Posted July 24, 2011 If you use 2553 for example, you can do full 8 bit display which will make your code much simpler. For example if P2 is used as 8 bit data to LCD, your code would like this (this is piece from my original ADC->LCD post, where I am not using send.asm.) The only thing, you will have to figure out encoder inputs since I'm using both ports. For example, you could use both ports to connect LCD, P1.0-P1.3 and P2.0-P2.3 or use just one port for encoder. I will wire it up and update my cod as soon as I find some time. #define sendData(data) send(data, 1) #define sendInstruction(data) send(data, 0) #define REGISTERSELECTPIN BIT5 // P1.5 #define ENABLEPIN BIT4 // P1.4 void sendDataArray(char data[], char length) { charIndex = 0; while(charIndex < length) { sendData(data[charIndex]); charIndex++; } } void send(char data, char registerSelect) { P2OUT = data; registerSelect ? (P1OUT |= REGISTERSELECTPIN) : (P1OUT &= ~REGISTERSELECTPIN); P1OUT &= ~ENABLEPIN; P1OUT |= ENABLEPIN; } Quote Link to post Share on other sites
Mac 67 Posted July 24, 2011 Share Posted July 24, 2011 Serial board is used to save pins, you need 6 or 10 to control HD44780.LP has 10 available pins so after 2 or 4 used for the encoder, you have enough to control LCD in 4bit mode (6 pins.) One way you might reduce that 2 to 4 pin overhead for the encoder (ouch!) would be to mux' the encoder switches with the LCD data lines and poll the switches periodically in software. Regards... kenemon 1 Quote Link to post Share on other sites
Mac 67 Posted July 24, 2011 Share Posted July 24, 2011 A variation of the previous design --> LCD interface and switch matrix on 6 pins. That's like getting the switch matrix for free (grin). Add two pins for a crystal and you're left with one pin for a "must have" piezo annunciator and one pin for a relay output. A potent single chip solution for that Clock/Calendar project, Alarm Clock project, or that Photo Timer / Appliance Timer project, etc... kenemon and bluehash 2 Quote Link to post Share on other sites
RobG 1,892 Posted July 24, 2011 Share Posted July 24, 2011 I guess it's the decision between simple software vs less pins used. You can sacrifice resolution and use only 2 pins instead of 4 for the encoder. kenemon 1 Quote Link to post Share on other sites
RobG 1,892 Posted July 24, 2011 Share Posted July 24, 2011 Here's the version that does not require serial board and uses 2553. The only other file you need from my previous posts is funct.asm. P1.0-P1.3 are connected to LCD's D0-D3 P2.4-P2.7 to LCD's D4-D7 P2.0 and P2.1 to encoder's A (with cap and pull-up resistor) P1.6 and P1.7 to encoder's B (with cap and pull-up resistor) P1.4 to LCD's enable P1.5 to LCD's RS LCD's R/W to GND LCD's GND, Vcc, Contrast, as required ( I tried with both, 3.3V and 5V, you can get 5V from LP's TP1.) #include "msp430g2553.h" //required funct.asm #define A1PIN BIT6 #define A2PIN BIT7 #define B1PIN BIT0 #define B2PIN BIT1 #define EINT P1IE |= A1PIN|A2PIN; P2IE |= B1PIN|B2PIN #define DINT P1IE &= ~(A1PIN|A2PIN); P2IE &= ~(B1PIN|B2PIN) #define CLRPFG P1IFG &= ~(A1PIN|A2PIN); P2IFG &= ~(B1PIN|B2PIN) #define LOWERNIBBLE BIT0 | BIT1 | BIT2 | BIT3 #define UPPERNIBBLE BIT4 | BIT5 | BIT6 | BIT7 #define ENABLEPIN BIT4 #define REGISTERSELECTPIN BIT5 #define sendData(data) send(data, 1) #define sendInstruction(data) send(data, 0) #define initDisplay() sendInstruction(0x3C); sendInstruction(0x0C); clearDisplay(); sendInstruction(0x06) #define clearDisplay() sendInstruction(0x01); _delay_cycles(2000) void binaryToASCIIScale(unsigned int n, unsigned char * digits, unsigned int scale); // asm prototype unsigned char d[5] = {0,0,0,0,0}; void sendDataArray(unsigned char data[], char length); void send(unsigned char data, unsigned char registerSelect); char charIndex = 0; char valueIndex = 0; int counter = 500; void main(void) { WDTCTL = WDTPW + WDTHOLD; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1OUT = ENABLEPIN; P1DIR = ENABLEPIN | REGISTERSELECTPIN | LOWERNIBBLE; P2SEL &= ~(BIT6|BIT7); P2DIR = UPPERNIBBLE; P1IES &= ~A1PIN; P1IES |= A2PIN; P2IES &= ~B1PIN; P2IES |= B2PIN; CLRPFG; initDisplay(); _bis_SR_register(GIE); EINT; while(1) { sendInstruction(0x80); binaryToASCIIScale(counter>>1, d, 0); sendDataArray(d, 5); _bis_SR_register(LPM0_bits); } } void sendDataArray(unsigned char data[], char length) { charIndex = 0; while(charIndex < length) { sendData(data[charIndex]); charIndex++; } } void send(unsigned char data, unsigned char registerSelect) { P1OUT &= 0xF0; P1OUT |= data & 0x0F; P2OUT &= 0x0F; P2OUT |= data & 0xF0; registerSelect ? (P1OUT |= REGISTERSELECTPIN) : (P1OUT &= ~REGISTERSELECTPIN); P1OUT &= ~ENABLEPIN; P1OUT |= ENABLEPIN; } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { DINT; if((P1IFG & A1PIN) ^ (P2IN & B1PIN)) { counter--; } else { counter++; } CLRPFG; EINT; _bic_SR_register_on_exit(LPM0_bits); } // Port 2 interrupt service routine #pragma vector=PORT2_VECTOR __interrupt void Port_2(void) { DINT; if((P2IFG & B1PIN) ^ (P1IN & A1PIN)) { counter++; } else { counter--; } CLRPFG; EINT; _bic_SR_register_on_exit(LPM0_bits); } If you need 2 more pins and do not require full resolution, just change defines and reuse pins P1.1 and P2.7 (ISRs should be updated too but it's not necessary.) #define A1PIN BIT6 #define A2PIN BIT6 #define B1PIN BIT0 #define B2PIN BIT0 If you need another 4 pins, you can drive LCD's 4bit mode and reclaim pins P1.0-P1.3 (several code changes are required.) Sidenote: This is actually a perfect example of why logical not arithmetic operators should be used for working with ports PxOUT |= BITA | BITB instead of PxOUT |= BITA + BITB I found many posts where statements were made that both yield same results and can be used interchangeably. This is true when all operands refer to a single unique bit (BIT0, BIT1, etc.) However, when operands refer to the same bit or more than one bits, using arithmetic operator will yield wrong results. For example: A1PIN and A2PIN are defined as bit 1 P1OUT |= A1PIN | A2PIN, will correctly set bit 1 P1OUT |= A1PIN + A2PIN, will incorrectly set bit 2 kenemon 1 Quote Link to post Share on other sites
Mac 67 Posted July 25, 2011 Share Posted July 25, 2011 I guess it's the decision between simple software vs less pins used. I wouldn't want to limit my creativity by thinking that way Rob (grin). You can sacrifice resolution and use only 2 pins instead of 4 for the encoder. Why can't you get full resolution with an encoder interrupt method using 2 pins instead of 4? I wonder if something like this might work? Couldn't you simply exclusive-or the P1IES 'A' or 'B' bit with the opposite 'B' or 'A' bit from P1IN to get "direction" and then toggle the P1IES interrupt edge select bit on your way out of the interrupt handler? Perhaps something like this (untested) example (both encoder pins on port 1)? #define old_A (P1IES & A_pin_mask) #define new_B (P1IN & B_pin_mask) #pragma vector = PORT1_VECTOR __interrupt void Port_1(void) { if(old_A ^ new_ // if direction = 1 counter--; // dec counter else // else counter++; // inc counter P1IES ^= P1IFG; // toggle edge select P1IFG = 0; // clr interrupt flag } kenemon 1 Quote Link to post Share on other sites
RobG 1,892 Posted July 25, 2011 Share Posted July 25, 2011 I guess it's the decision between simple software vs less pins used. I wouldn't want to limit my creativity by thinking that way Rob (grin). You can be creative but you have to weight your options. If you end up with some spare pins because you used mux, I think simplifying your software should be considered. Why can't you get full resolution with an encoder interrupt method using 2 pins instead of 4? I wonder if something like this might work? Couldn't you simply exclusive-or the P1IES 'A' or 'B' bit with the opposite 'B' or 'A' bit from P1IN to get "direction" and then toggle the P1IES interrupt edge select bit on your way out of the interrupt handler? Perhaps something like this (untested) example (both encoder pins on port 1)? Looks like that should work, I will give it a try tonight. I wasn't crazy about switching IES, but I think our combined effort gave us some nice results. I wish I had better encoder though, those PEC11s are really awful, I get pretty nice results on one half of the turn, really bad on the other. On the other hand, if we can get crappy one to work, than all other will work too kenemon 1 Quote Link to post Share on other sites
Mac 67 Posted July 25, 2011 Share Posted July 25, 2011 I guess it's the decision between simple software vs less pins used. I wouldn't want to limit my creativity by thinking that way Rob (grin). You can be creative but you have to weight your options. If you end up with some spare pins because you used mux, I think simplifying your software should be considered. What I was trying to say, as politely as possible, was that your statement was bull. It seemed that you were suggesting, and are continuing to suggest, that I can't write "simple" code for a solution that uses less pins, and I disagree with that. I take a lot of pride in writing clean, clever, simple, and elegant code. On the other hand, maybe I misunderstood. Were you perhaps trying to say that you can't write "simple" code for a solution that uses less pins? Looks like that should work... I'm sorry I don't have any way to test it but if it does work I think you'll agree it's pretty simple while using less pins without sacrificing resolution (grin). I wish I had better encoder though, those PEC11s are really awful ... I agree. It seems like a very cheap mechanism. kenemon 1 Quote Link to post Share on other sites
RobG 1,892 Posted July 25, 2011 Share Posted July 25, 2011 Looks like that should work... I'm sorry I don't have any way to test it but if it does work I think you'll agree it's pretty simple while using less pins without sacrificing resolution (grin). When talking about simple, I was talking about multiplexing, not just reducing pin count by 2. Anyway, I tried this... __interrupt void Port_1(void) { DINT; if((P1IES & A1PIN) ^ (P1IN & A2PIN)) { // A1PIN is A, A2PIN is B counter--; } else { counter++; } (P1IFG & A1PIN) ? (P1IES ^= A1PIN) : (P1IES ^= A2PIN); // toggle appropriate edge select CLRPFG; EINT; _bic_SR_register_on_exit(LPM0_bits); } ...and it works, but unreliably. Not sure if it's the encoder or the code, but the 4pin solution seems to be working a lot better. What I was trying to say, as politely as possible, was that your statement was bull. It seemed that you were suggesting, and are continuing to suggest, that I can't write "simple" code for a solution that uses less pins, and I disagree with that. I take a lot of pride in writing clean, clever, simple, and elegant code. On the other hand, maybe I misunderstood. Were you perhaps trying to say that you can't write "simple" code for a solution that uses less pins? All I stated was that multiplexing requires more code because you have to juggle inputs and outputs. I can't comment on your code because honestly, I haven't seen any. It is a lot easier to improve and critique someone's work than to come up with it in the first place. Let's leave it at that. kenemon 1 Quote Link to post Share on other sites
Mac 67 Posted July 25, 2011 Share Posted July 25, 2011 I wasn't critiquing your work Rob. You do nice work. I was just trying to debunk the myth in your statements. They seemed a little off-the-cuff, more like opinion and assumption than fact, and seemed like undue criticism of a valid suggestion. I'll leave it at that too. My apologies for ruffling your feathers and for allowing your statements to ruffle mine... Cheerful regards, Mike Quote Link to post Share on other sites
kenemon 29 Posted July 26, 2011 Author Share Posted July 26, 2011 you guys never fail to blow my mind. Two incredible ways to attack this problem, cant wait till i get a moment to put them to work. Thanks. KB Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.