Write EEPROM By Pin Problem - Page 1
Forum section: electronics / general

author: ed_reardon
author_rank: Regular Contributor
timestamp: February 06, 2018, 07:58:15 am
content: Hello all,I'm working on a stepper motor controller program, it all works great except this single issue I'm having.As these stepper motors were not cabled identically, the program does have a 'programming' sequence where the service tech' can set the motor direction (it only spins in one direction for its entire life) during the initial setup, this would only be carried out once a decade or so. The idea is the uC can be started with a resistor held to pin RB3 if the direction needs changing, the RB3 pin is disonnected from the ground plane of the PCB by virtue of being fitted in a socket with the pin cut off!I am using the EEPROM elsewhere in the program and it works fine, so I'm happy with the read/write functions I've written, I just can not get this programming to work. If I step through the program using the virtual pins in MPLAB it all works splendidly, but not in the real world:Code://---------------Direction programming Prototype-----------////--------------Only to run during prime cycle------------//void PROG_DIR (void){if (DIR == 1){ //Check for current configurationwrite_eeprom(0x01, 00); //Write DIR value to 0 in EEPROMwrite_eeprom(0x00, 01); //Write USERCONFIG flag}else {write_eeprom(0x01, 01); //Write DIR value to 1 in EEPROMwrite_eeprom(0x00, 01); //Write USERCONFIG flag}DIR = EEread_b(0x01); //Reload DIR value from EEPROM}//-----STARTUP PRIME Prototype------------------------------------------//void prime (void){//Set up TIMER1//T1Count = 2; //Load T1countT1CONbits.TMR1CS=0; //Derive Timer1 from FOSCT1CONbits.T1CKPS=01; //Use 1:4 PrescalerT1CONbits.TMR1ON=1; //Turn Timer1 On.//----//while (T1Count>2){ //Wait for Timer1 to reach 2pump (T1Count);}T0CONbits.TMR0ON=1; //Switch on Timer0//Check for programming pin HIGH status//TRISBbits.RB3 = 1; //Turn on RB3 Inputif (PROG == 1){PROG_DIR();}TRISBbits.RB3=0; //Turn off RB3 Input//----//while (T0Count <5){ //Run fast prime for approx 50spump(2); //Fast Prime Pump Speed}T0CONbits.TMR0ON=0; //Switch off Timer0T0Count=0; //Reset Timer0 CounterT1CONbits.TMR1ON=0; //Switch off Timer1T1Count=0; //Reset Timer1 Count}The 'Prime' function calls the 'Prog' function if the pin is high, if not it carries on.Any suggestions what may be causing this not to work in practice?Cheers,Ed

author: donotdespisethesnake
author_rank: Super Contributor
timestamp: February 06, 2018, 10:08:12 am
content: QuoteCode:TRISBbits.RB3 = 1; //Turn on RB3 Inputif (PROG == 1){PROG_DIR();}TRISBbits.RB3=0; //Turn off RB3 InputLooks like PROG_DIR() is called if PROG is 1. I don't see where RB3 is read in? Is there relevant code you have not shown us?

author: obiwanjacobi
author_rank: Super Contributor
timestamp: February 06, 2018, 11:22:55 am
content: So you have floating input pin?Does it have a pull up or down enabled?

author: ed_reardon
author_rank: Regular Contributor
timestamp: February 06, 2018, 03:53:29 pm
content: Cheers all,It's defined at the top of the program in:Code:#define _XTAL_FREQ 8000000 //Define XTAL ref for _delay function#define PULSE LATAbits.LATA0 //RA0 Defined as PULSE pin#define DIR LATAbits.LATA1 //RA1 Defined as DIRECTION pin#define SPEED PORTBbits.RB0 //RB0 Defined as PRIME control pin#define PROG PORTBbits.RB3 //RB3 Defined as Direction Programming PinI've also tried turning on the internal pull-up and using the value of zero (pin bridged to ground) but still nothing as:Code:void prime (void){//Set up TIMER1//T1Count = 2; //Load T1countT1CONbits.TMR1CS=0; //Derive Timer1 from FOSCT1CONbits.T1CKPS=01; //Use 1:4 PrescalerT1CONbits.TMR1ON=1; //Turn Timer1 On.//----//while (T1Count>2){ //Wait for Timer1 to reach 2pump (T1Count);}T0CONbits.TMR0ON=1; //Switch on Timer0//Check for programming pin HIGH status//TRISBbits.RB3 = 1; //Turn on RB3 InputINTCON2bits.RBPU = 0; //Turn on PULL UP on PortBif (PROG == 0){PROG_DIR();}TRISBbits.RB3=0; //Turn off RB3 Input//----//while (T0Count <5){ //Run fast prime for approx 50spump(2); //Fast Prime Pump Speed}T0CONbits.TMR0ON=0; //Switch off Timer0T0Count=0; //Reset Timer0 CounterT1CONbits.TMR1ON=0; //Switch off Timer1T1Count=0; //Reset Timer1 Count}Still confusedCheers,Ed

author: JPortici
author_rank: Super Contributor
timestamp: February 06, 2018, 04:03:43 pm
content: I'll never stop saying it: I don't like reading pins this way. Never found it reliable.It SHOULD translate to single BTFSS/BTFSC or whatever instructions in 16/32 bit parts, but it never worked reliably for me.Sample the port.Test by masking the sampled port.Much more reliable results.Code:uint8_t PORTB_sample;[..]PORTB_sample = PORTB;if (!(PORTB_Sample & (1 << 3))) {//Same as if (PORTBbits.PORTB3 == 0)//! negates, so true if zero//1 << 3 because i find it easier than "8" to remember as "Bit 3"}

author: Andy Watson
author_rank: Super Contributor
timestamp: February 06, 2018, 04:08:07 pm
content: DIR appears to be defined as the latched-bits. So you are reading the value that was last written to the port pin - which, at this stage of the program, appears to be undefined.

author: JPortici
author_rank: Super Contributor
timestamp: February 06, 2018, 04:44:27 pm
content: as per his latest post he's reading "PROG" which is defined as PORTBbits.RB3. the value of PORTB is updated during the instruction cycle reflecting the state of the pin, regardless if it's an input,output, GP or controlled by a peripheral (unless it's programmed as Analog)

author: Andy Watson
author_rank: Super Contributor
timestamp: February 06, 2018, 04:56:50 pm
content: I agree that PROG is being used correctly, however, since prime appears to be part of an initialisation sequence, and we've not been shown any prior code, I was questioning the value of DIR - which (considering the posted code) appears to either be undefined, or read as input from RA1 - either way, it appears not to be defined until after it is used to toggle its state! Unless, of course, there is more code that we've not seen.

author: ed_reardon
author_rank: Regular Contributor
timestamp: February 06, 2018, 06:26:45 pm
content: Cheers all, okay this is a bit of a weird one - I've written the software to load the EEPROM values in to the int values (sort of self programming) after checking to see if the user has redefined the standard values, this is done here:Code://------------Initialisation of EEPROM Prototype------//void checkinit (void) {userprog = EEread_b (0x00);if (userprog != 1){write_eeprom (0x01, 1); //Set DIR to '1'write_eeprom (0x02, 54); //Set MEDTIME to '54' *********CRITICAL***********write_eeprom (0x00, 1); //Set Programming flag high.}else; // If chip already configured by user, escape prototype.}Code://-----------------READ IN Prototype--------------//void read_in (void){DIR = EEread_b (0x01);MEDTIME = EEread_b (0x02);}It's called here at the top of the program, before the loop:Code:checkinit(); //Check to see if user has configured chipread_in(); // Load in parameters from EEPROM/* startup_delay(); // Startup delay to compensate for power-on relay delay */prime(); // Run FAST-PRIME ProdecureThe delay has been commented out for my sanity whilst testing on the bench (it's a 60s delay, it's irritating whilst testing!)I hope this thins, (or indeed thickens) the plot, as the program otherwise works flawlessly, it seems that pulling values in-and-out of the EEPROM and assigning them isn't an issue.Cheers,Ed

author: Nusa
author_rank: Super Contributor
timestamp: February 06, 2018, 06:59:34 pm
content: Try inserting a 1 ms delay between turning the pin on and reading it. My theory is you're reading the pin before the input is stable. If that's it, obviously 1 ms is way longer than needed, but it's fine for a first test.

author: ed_reardon
author_rank: Regular Contributor
timestamp: February 06, 2018, 07:12:12 pm
content: 1ms is absolutely fine, this isn't a timing critical application, the timers are near enough to about 15s!It's for an industrial pump system in a non-critical/non-safety application, this is just a refinement of the standard software to tidy up a few irritating things about the standard software.I'll give it a try!Cheers,Ed

author: NorthGuy
author_rank: Super Contributor
timestamp: February 06, 2018, 07:41:53 pm
content: I don't quite understand why you're doing this. If someone cuts off the pin, it is not going to grow back, right? So, you can simply read the state of the pin at the beginning every time such as:Code:DIR = PROG;That's all you need (except configuring pins and enabling pull-ups).This has an added advantage that if they do want to change the direction afterwards, they simply solder back the pin. It is much better for the people in the field than going through your complex "imprinting" procedure.

author: cv007
author_rank: Frequent Contributor
timestamp: February 06, 2018, 08:06:35 pm
content: Maybe I missed it, but which chip is this? It would probably help if it was known.For example, you may have a chip where RB3 has an alternate use where its fused on to that alternate use, causing the digital in to read as 0.just looking at previous posts, the OP may be using a PIC18F1330?from datasheet-On a Power-on Reset, PORTB isconfigured as digital inputs except for RB2and RB3.RB2 and RB3 are configured as analoginputs when the T1OSCMX bit of ConfigurationRegister 3H is cleared. Otherwise,RB2 and RB3 are also configured asdigital inputs.

author: ed_reardon
author_rank: Regular Contributor
timestamp: February 06, 2018, 08:53:31 pm
content: Quote from: cv007 on February 06, 2018, 08:06:35 pmYes, sorry that was entirely my error, it's PIC18F1330, different application than last time though!Interesting about the registers.I think the part about cutting the pin might be a consideration!

author: ed_reardon
author_rank: Regular Contributor
timestamp: February 06, 2018, 09:07:08 pm
content: Quote from: NorthGuy on February 06, 2018, 07:41:53 pmSorry I don't think I explained the intention very well.These control stepper motors which were not identically cabled, some will spin CW with DIR pin high, some CCW.The pump, for its entire life must only spin CW, there is no need for it to spin CCW at all, ever.Now, obviously the sensible answer is to reverse a winding, however this is a bit of a pig of a job on this machine, the terminals are 'well buried' so when the new uC is installed it's pretty much a 50/50 as to which way the motor will spin.My thought (although I think I've coded it impossibly badly) was that the state of the direction pin (high or low) could be stored in EEPROM then adjusted during the start up cycle by simply physically holding a resistor to the programming pin and reversing the status of the direction pin until such a time the motor is changed or something else curious happens. This can then be left alone for years at a time and merrily run in the correct direction.The bit about 'cutting the pin off' wasn't explained well by myself:This is using an existing board where RB3 was never utilised and was just held low, I've installed the test uC's in a socket with the RB3 pin cut off (so the chip isn't damaged, just the socket) this breaks the connection between RB3 and ground that'd I'd have by just plugging the chip in.You know, somehow, I think I've explained this in an even more complicated way!Basically tech' can as an installation job restart with a resistor held to RB3 if the motor spins backwards on power up, DIR pin status is reversed, life goes on....Does that make any more sense, or am I making this more obtuse!Cheers,Ed

author: cv007
author_rank: Frequent Contributor
timestamp: February 06, 2018, 09:26:19 pm
content: simply double-check- T1OSCMX bit of Configuration Register 3Htwo possibilities, and one of them would cause your problem

author: NorthGuy
author_rank: Super Contributor
timestamp: February 06, 2018, 09:32:11 pm
content: I see. The logic you have is rather complex. As you describe, you only need to do the following (in pseudo-code):Code:DIR = READ_EEPEOM(ADDR_OF_DIR); // Is ready to spin the motor in some direction.// The direction will be the same from statt to start because it is read from EEPROM// Doesn't matter how it is initialized because we don't know the correct direction anywayif (~PROG) {// Oops; someone holding the pin short, which means the motor would spin in the wrong direction.// Need to change the direction to the correct oneDIR = ~DIR;// and remember this for future starts.WRITE_EEPROM(ADDR_OF_DIR,DIR);}It would be nice to have a push-button instead of holding a wire against the pin - not all people have good vision and steady hands.Also. I wouldn't trust the built-in pull-up around the motors and install a stronger external one.

author: ed_reardon
author_rank: Regular Contributor
timestamp: February 06, 2018, 09:38:54 pm
content: Good point, the register is HIGH in my pragmatic setup though.@NorthGuy - yes, you can tell I'm a very green programmer can't you, I'm a touch 'verbose' at the moment, I like to hack something together, then print out the code and physically start slashing away at it with a pencil until I can whittle it in to something that makes more sense, or at least a good deal more efficient!Thank you all for your help, it truly is appreciated.

author: Nusa
author_rank: Super Contributor
timestamp: February 06, 2018, 10:17:01 pm
content: Or, since there's only two possibilities, simply have a configuration switch/jumper pins/solder pads connected to that pin that the tech can permanently change. Then you wouldn't need to save the value in eeprom.