PDA

View Full Version : Writing and reading bits and memory



ERMEGM
- 29th January 2012, 22:29
Hi Guys,

Having a little problem with my code and can’t seem to see where the problem lies. Here’s what I’m trying to do. I have two inputs, a record button and two outputs. What I’ve attempted so far in my code is that when the record button is pressed, the program samples both inputs (inputs are driven high and pulled low) and writes the value in eeprom in bits at timed intervals. Because you cannot read and write to the eeprom in bits, I’ve created a routine that when in record mode, puts each bit value (1 or 0) in a temporary array and when the array is filled, that array is written to a memory position until the allotted memory space is filled or the program button is released. Recording time has a limit, however can be stopped at anytime.

Once released, the program now plays back what was just recorded. It takes the byte array from memory and places it in a temporary array. The program reads and displays each bit until all 8 bits are read and then grabs the next byte array.

Seems pretty simple and straight forward, however, I am getting unpredictable results. When I setup the circuit and program the chip, it does what it’s supposed to do when entering program mode, however, playback is playing back some of what I entered and then stuff I never entered.

I setup the inputs as tactile switches for manual operation. My test consisted of simply alternating presses from left to right. What is repeated is the same alternating LEDs and then both will flash on at once at random intervals. When I hold down one button, I should get a continuous replay of one LED lit, so it looks like it has constant power. Instead I get something weird. If I record a button press on gpio.1 for 3 seconds, then I get LED1 (gpio.5) on for 3 seconds and then both come on for 1 second and then back to LED1 on for 3 seconds. However, if I record a button press on gpio.2 for 3 seconds, then I get LED2 (gpio.4) on for 3 seconds and then both LEDs are out for 1 second and then back to LED2 on for 3 seconds. What is my code doing?

Shouldn’t each recording session overwrite each bit as I am writing over it? Can someone take a look and see what I’m missing? The circuit should sample the two inputs. They are always high unless pulled low. It should then take each value, put it into bit location 0, wait 100 ms and then repeat, but this time putting the next value into bit location 1 and so on until 7 is reached. When all 8 bits have filled the array, that temporary array writes it to memory (L_state[0] or R_state[0]). I allotted 30 bytes for each array in memory for this (runtime is about 24 seconds of recording). A counter assigns each location. On playback, the routine is reversed. The program reads L_state[0] or R_state[0], places each byte array into their own temporary array (leftvalue and rightvalue) and then reads each bit from 0 to 7 and displays it on the outputs at the same timed interval. In essence mimicking what the inputs were doing.

I am using a 12F683 which has 128 bytes of RAM and 256 bytes of eeprom. I am running PBP 2.60. Any help would be greatly appreciated.


' -----[ Initialization ]--------------------------------------------------
Reset:
OPTION_REG.7 = 0 ' Pullups enabled
WPU = 0000 ' Weak Pull Up
GPIO = 0000 ' sets outputs as high (1) or low (0)
TRISIO = 1111 ' sets pin as input (1) or output (0)
ANSEL = 0 ' Disable analog inputs
CMCON0 = 7 ' Disable comparators


leftvalue and rightvalue are the temporary arrays for reading and writing the bits for the arrays.


' -----[ Variables ]-------------------------------------------------------

record var gpio.0 ' program button input

leftbutton var gpio.1 ' left button input
rightbutton var gpio.2 ' right button input

rightled var gpio.4 ' right led output
leftled var gpio.5 ' left led output

leftvalue var byte ' stores the opposite value of the button
rightvalue var byte ' stores the opposite value of the button

counter var word ' counts how many bits are being used
limit var word ' stores the last count value for the loop

L_state var byte[29] ' create 232 bits for storing 90 seconds
R_state var byte[29] ' worth of patterns for both left and right leds

x var byte ' variable for bit count
y var byte ' loop variable for output flash


Here is where the writing occurs. Because the inputs are high and pulled low, I had to invert the value stored so it would reflect a button press and not the value.

' -----[ Program ]---------------------------------------------------------

flash:

for y = 1 to 3 ' flash outputs three times
high leftled
high rightled
pause 500
low leftled
low rightled
pause 500
next y

counter = 0 ' reset counter value to 0

program:

while record = 0 ' while record button is pressed, loop here

if counter = 30 then finish ' if 24 seconds is reached, exit program mode

For x = 0 to 7

if leftbutton = 0 then ' if left buttton has been pressed,

leftvalue.0[x] = 1 ' then write an "on" value
else
leftvalue.0[x] = 0 ' then write an "off" value
endif

leftled = leftvalue.0(x) ' display on led

if rightbutton = 0 then ' if right button has been pressed,

rightvalue.0[x] = 1 ' then write an "on" value
else
rightvalue.0[x] = 0 ' then write an "off" value
endif

rightled = rightvalue.0[x] ' display on led

pause 100 ' pause 1/10th of a second

next x

write L_state[counter], leftvalue
write R_state[counter], rightvalue

counter = counter + 1 ' advance counter by 1

goto program

wend

limit = counter ' write counter value to limit

counter = 0 ' reset counter value to 0

goto action ' return to action

Here's where the reading happens.

' -----[ Action ]----------------------------------------------------------

action:

FOR counter = 0 TO limit ' start reading bit locations

read L_state[counter], leftvalue ' read the array of bits and place in left value
read R_state[counter], rightvalue ' read the array of bits and place in right value

for x = 0 to 7

leftled = leftvalue.0[x] ' left led will mimic bit value
rightled = rightvalue.0[x] ' right led will mimic bit value

pause 100 ' pause 1/10th of a second

next x

if record = 0 then program ' If program button is pressed, then
' goto program mode

NEXT counter

goto action

This is where the program goes if the time limit is exceeded.

' -----[ Exit Program ]----------------------------------------------------

finish:

while record= 0 ' loop here while program button is held

low leftled
low rightled

pause 500 ' just wait 1/2 a second

goto finish ' continue loop

wend ' exit loop when button is released

limit = 29 ' write counter value to limit

goto action ' return to action


I know this seems like a lot of stuff when attempting to implement this program, however, this coding is modified from another program I wrote that is presently working. I merely substituted the bit writing in the appropriate places to get more "recording time". The other program worked perfectly, but with less "recording time".

Thanks,
Tony

Dave
- 30th January 2012, 01:46
Ater each write to eeprom, place a "PAUSE 6". This will allow enough time for the write to complete for that byte. Let us know...

Demon
- 30th January 2012, 01:47
(stuff removed)

Ok, it's all in my edits now. :)

Robert


EDIT: You said your previous version worked, did you have a delay in that version and then took it out?

EDIT SOME MORE: Is there a particular reason why you use those GOTO at the end of both WHILE RECORD=0?

EDIT YET AGAIN: by the way, byte[29] will create elements 0 thru 28. Writing element 29 will write "somewhere", but most likely not where you want.

EDIT ONE LAST TIME: I'm curious, just how fast are you on those buttons anyways? :D You loop 29 times with a 10th of a second each loop, you gotta be pretty quick! That's just under 3 seconds to enter all those key presses isn't it? (or did I miss something?)

ERMEGM
- 30th January 2012, 12:00
Hi Dave,

Tried the pause after each write command and now it's behaving even worse.

Hi Demon,

My last version I used wrote to bytes and not bits. Only got about 20 seconds (max) of record time. Was trying to extend it by writing to bits. I chose 29 bytes (about 24 seconds worth of recording) because I wanted to test the max out feature and was saving time by setting a lower limit. Once the code works, then I will increase the time.

As for the goto; you know, that is kind of redundant. It automatically does that with the while..wend loop. I must have done that for some other code in the past and just didn't think anything about it. I will correct that and see if it does anything.

I will fix the 29 bytes address, however, that should only be an issue when you max out the count, correct? If I only record for 3 seconds, I shouldn't get the playback I'm getting. Will fix that as well.

As for the 29 bytes and 100ms pauses; I'm trying to record inputs of varying lengths. The best way I know how is to test the inputs multiple times per second. That way if I press the left input or right input or both at varying lengths, it should be able to repeat that the left button was held for 7/10 of a second while the right was held for 9/10 of a second. 1/10 of a second come out to 8/10 of a second per byte. 29 bytes is 24 seconds. I will be increasing that time by increasing the bytes being used, however limited the time for testing purposes. That, at least, was my logic.

Tony

Dave
- 30th January 2012, 12:04
Robert, The last time I did the math, 30 x 8 x .1 is more than 3 seconds....

Dave
- 30th January 2012, 12:09
Tony, Is what you are showing us the complete code? Do you have any interrupts enabled?

Demon
- 30th January 2012, 15:02
Robert, The last time I did the math, 30 x 8 x .1 is more than 3 seconds....

Bingo!

I forgot the FOR loop.

Robert

ERMEGM
- 31st January 2012, 01:00
Tony, Is what you are showing us the complete code? Do you have any interrupts enabled?

Yes it is. No interrupts. The only thing I noticed is that the "%00" was removed from my Initialization screen. Per the recommendations, L_state and R_state have been changed to 30 bytes and Counter has been changed to 31 instead of 30 in the program loop and pause 6 has been added after the write commands.

The removal of the two goto's did help fix some irratic behavior, but still having the same problem of not playing back correctly.

Tony

andywpg
- 31st January 2012, 03:16
Just a random thought here.

I'm very new to PBP (but not to microcontrollers, or BASIC for that matter), but I really don't see anywhere that you are debouncing your switches. Could this be as simple as garbage getting in from bounce?

Or am I missing something (usually the case.....)

ERMEGM
- 31st January 2012, 05:06
True, but that does not explain when holding down one button for a constantly lit LED that both will flash. I used this setup on my other program that wrote to bytes instead of bits, and it worked flawlessly.

Dave
- 31st January 2012, 11:35
Tony, Please attach the entire program in 1 segment for our viewing from configs to end...

ERMEGM
- 2nd February 2012, 16:15
OK. Completed the code and things are working great now. Thanks to Darrel (DT), he explained a few things that I was doing wrong and clarified my understanding of what I thought was happening and what was really happening. After a few days of trial and error, I got it working perfectly. To clear up where the problem were, the following changes were made.

1) Didn't need to make two arrays (L_state and R_state). One array served just fine and a (+ 1) went on the second byte values so that all the left inputs went into the even memory slots and the right inputs went into the odd memory slots.

2) There was no need for four lines of code to invert the input value. The ! command took care of that (leftvalue.0[x] = !leftbutton)

3) Wasn't writing my limit to eeprom, so the value erased itself when power was removed.

So the major changes are:


EE_Limit DATA @254,WORD 0

Reset:

OPTION_REG.7 = 0 ' Pullups enabled
WPU = %000000 ' Weak Pull Up disabled because of my external pullups
TRISIO = %001111 ' sets pin as input (1) or output (0)
ANSEL = 0 ' Disable analog inputs
CMCON0 = 7 ' Disable comparators

' -----[ Variables ]-------------------------------------------------------

record var gpio.0 ' program button input
leftbutton var gpio.1 ' left button input
rightbutton var gpio.2 ' right button input

rightled var gpio.4 ' right led output
leftled var gpio.5 ' left led output

leftvalue var byte ' stores the opposite value of the button
rightvalue var byte ' stores the opposite value of the button

counter var word ' counts how many bits are being used
limit var word ' stores the last count value for the loop

x var byte ' variable for bit count
y var byte ' loop variable for output flash

' -----[ Action ]----------------------------------------------------------

action:

READ EE_Limit , WORD limit

FOR counter = 0 TO limit Step 2' start reading bit locations

read counter, leftvalue ' read the array of bits and place in left value
read counter + 1, rightvalue' read the array of bits and place in right value

for x = 0 to 7

leftled = leftvalue.0[x] ' left led will mimic bit value
rightled = rightvalue.0[x] ' right led will mimic bit value

pause 100 ' pause 1/10th of a second

next x

if record = 0 then flash ' If program button is pressed, then
' goto program mode

NEXT counter

goto action

' -----[ Program ]---------------------------------------------------------

flash:

for y = 1 to 3 ' flash outputs three times
high leftled
high rightled
pause 500
low leftled
low rightled
pause 500
next y

counter = 0 ' reset counter value to 0

program:

if record = 1 then action ' if the program button was momentarily pressed,
' return to action loop
while record = 0 ' while record button is pressed, loop here

if counter = 60 then finish ' if 24 seconds is reached, exit program mode

for x = 0 to 7

leftvalue.0[x] = !leftbutton ' store inverted value of leftbutton
leftled = leftvalue.0[x] ' display on led

rightvalue.0[x] = !rightbutton ' store inverted value of rightbutton
rightled = rightvalue.0[x] ' display on led

pause 100 ' pause 1/10th of a second

next x

write counter, leftvalue
write counter + 1, rightvalue

counter = counter + 2 ' advance counter by 2

wend

limit = counter - 2 ' write counter value to limit

WRITE EE_Limit , WORD limit

goto action ' go to action and run pattern

' -----[ Exit Program ]----------------------------------------------------

finish:

while record = 0 ' loop here while program button is held

low leftled
low rightled

pause 500 ' just wait 1/2 a second

wend ' exit loop when button is released

limit = counter - 2 ' write counter value to limit

WRITE EE_Limit , WORD limit

goto action ' return to action