Shop OBEX P1 Docs P2 Docs Learn Events
Propeller based XBEE Remote for Christmas Play Time Machine prop — Parallax Forums

Propeller based XBEE Remote for Christmas Play Time Machine prop

WBA ConsultingWBA Consulting Posts: 2,933
edited 2017-11-16 21:19 in Customer Projects
(former title: "resolved.... Buggy reads from 4x4 Keypad to Propeller using 4x4 Keypad Reader.spin")

I am trying to wrap up a project today for a Christmas play TOMORROW MORNING!. See this thread and this thread for details. In fact, I am typing this as the dress rehearsal is about to begin and my prop (a time machine) is not working correctly because the keypad is giving false inputs. So for the dress rehearsal I am using my laptop with an XBEE on a USB adapter and PST to send my keycodes to the time machine (that works the different jumps).

I am using 4x4 Keypad Reader.spin from the OBEX and the Parallax 27899 4x4 Matrix Membrane Keypad. The membrane keypad is connected DIRECTLY to a Propeller Mini, no extension cable.

However, as I push buttons on the keypad, I get a handful of misreads. For example, pressing the #5 key will respond with either the 4 or 5 response (totally random, but usually the first keypress is always incorrect), pressing the #0 key will give a 1 or a 0 response. I have found a few threads talking about adding pullups, pulldowns, or caps to the lines when using extension cables, but I am not using anything bu the keypad.

http://forums.parallax.com/showthread.php/147464-keypad-reader-doesnt-work?highlight=matrix+keypad
http://forums.parallax.com/showthread.php/136400-Issue-with-4x4-input-matrix?highlight=matrix+keypad

In the remote case which has the keypad on the front is:

Propeller Mini
XBEE SIP Adapter
XBEE Module
9 volt battery
4x4 keypad

What else should I look at before I start ripping things apart? I will play with adding caps and resistors on another board to see the differences.

My keypad code is attached.

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-12-14 11:26
    I would still terminate the input lines. If the switches pull to ground, use pullups on the Prop inputs; if to Vdd, use pulldowns. Without any kind of load, the slightest bit of crosstalk can lead to a false read, even without a cable (e.g. between adjacent Prop pins).

    -Phil
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-14 11:38
    Thanks Phil, I was thinking exactly that, but since the setup in the case is so small, I didn't want to start hacking parts onto it. I do have the keypad cable looped around the Propeller Mini, so maybe that's the cause.

    (the laptop-->serial terminal-->xbee usb adapter-->xbee setup for the dress rehearsal worked well at least)
  • Beau SchwabeBeau Schwabe Posts: 6,545
    edited 2013-12-14 13:25
    WBA Consulting,

    With this object, it's important to keep the keypad lines as close as possible to the Propeller.
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-14 14:15
    Beau,
    Yes, I have the keypad flex cable plugged into a header soldered to the propeller mini, so I can't get any closer. If the flex is that easily an issue, maybe a comment should be added to the product page or object.
    I will take a picture of the setup and add it so you can comment on the flex cable positioning.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-12-14 14:18
    I was having trouble with the keypad object. I had relatively long wires so I added 0.1uF cap to either the columns or the rows (I don't recall which) and the problems went away. I know I suggested this same fix to another forum member with similar trouble who also reported the caps fixed the issue.

    Edit: I see I suggested the same thing in the two threads linked to in the OP. At least I'm consistent (one was almost word for word).
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-14 14:57
    Here is a pic of inside the remote. Keypad is underneath the xbee.

    (Added front pic, the number stickers added match cue numbers in the script)
    1024 x 768 - 68K
    1024 x 1365 - 118K
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-14 14:58
    Duane, as I was reading your post I was thinking that I had read it before, LOL.......
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2013-12-14 15:38
    "as I was reading your post I was thinking that I had read it before..."

    It is a time machine you are making
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-12-14 16:43
    Andrew,

    You marked the thread "solved" but didn't say how you solved it.

    -Phil
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-14 16:47
    Oops, was going to mark it solved since I had several solutions but changed my mind. Apparently, I hit submit before exiting the page. I will fix it.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-12-14 17:08
    Andrew,

    I had a peek at the keypad object you're using. It's a novelty, to be sure, but I don't see how the method can possibly be reliable. I would definitely add pulldowns to the four input pins. You can probably use the same object, but the discharge step will be superfluous.

    -Phil
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-14 17:31
    Sounds good. I did look at the prop mini where IO pins 4-7 are and I think I can squeeze in four 10k SMT resistors between the header pins and the neighboring ground plane if I scrape some of the soldermask off. I plan on keeping this prop mini and keypad in this case for other projects, so I want to keep things small to leave room for other things I may add later. The xbee SIP adapter will be going away and be replaced by an xbee that has the headers removed and a small 4 wire cable soldered on.
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-14 21:12
    Well, that did the trick! I looked through my stash and found 10k in both 1206 and 0402 packages. The 1206 would be easier to solder, but would only fit if soldering partially up the header. The 0402s would be more difficult to solder, but would drop right into place perfectly. I took the challenge and began scraping tiny spots of the soldermask. Using tweezers to hold and place the 0402s, I soldered them into place. To my amazement, the 0402s came out beautifully (I don't mean to toot my own horn, but this is probably my tiniest ever mod done at home, I truly shocked myself) I will get pictures next week when I can take some under a microscope. (although they may not look great under a microscope, but we'll see)

    So, I soldered the resistors, re-assembled the remote, and gave it a whirl. Absolutely solid response, not a single error in a random stream of about 50 presses. Marking this thread to solved. When I do the project write-up, I will be sure to reference this thread and the membrane keypad concerns to help others.
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-16 12:30
    So, I took a couple shots of the resistor mods under a microscope and I am still shocked at my results. I guess I have more reason to say that the best present I have ever received was the laser eye surgery from my wife for my 40th birthday!

    Anyhow, the picture shows four 10k, 0402 resistors soldered from 4 ground pads to the header tied to P4-P7. The 4 ground pads were created by scraping soldermask off the groundplane with an X-acto knife.
    1024 x 768 - 122K
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-12-16 14:49
    I didn't know solder would stick to ground black pepper!

    -Phil
  • electromanjelectromanj Posts: 270
    edited 2013-12-16 15:52
    Thumbs up man!

    What type of magnifier did you use?

    If the answer is none, can we go to the casino together? :D
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-16 16:41
    What type of magnifier did you use?

    None, did this with eyes behind safety glasses only. That is why I am shocked as well.
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2013-12-17 15:25
    Finally loaded up one of the videos from the Time Machine prop. The volume is a little low and somewhat muffled; plus the LED strips are a bit bright for the phone's camera. I'll have better video once I copy the actual play from my camcorder.

    This is the Time machine jumping from 2013 to 1978
    http://www.youtube.com/watch?v=QYMjnMPeGqU

    This is a keypad entry sequence where the month and day are entered, but no year (thus causing part of the problem of the time machine jumping to random years)
    http://www.youtube.com/watch?v=EyhqAzLbkiE
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2017-11-16 21:29
    FULL STORY:

    These are my notes from a word doc started years ago to make a thread specifically for the final project. I never actually made the thread, but trying to post more details here for others.


    My daughter was part of a Christmas play for our church in 2013 called “Back to the Manger”. I The play is about a church custodian that invents a time machine and during a Christmas outreach program, a group of kids activated it before all the bugs were worked out and end up jumping through a bunch of years. The play was done a few years prior with only a cardboard prop, so this time we wanted to step it up a bit.

    I thought about how the propeller can display VGA extremely easy, so showing the year as it traveled back in time should be simple to do and would look pretty cool for the prop. I also figured I could add a bunch of LEDs and drive them with the digital IO board. Sound effects from the CD for the play were converted to wave files to play out computer speakers. To cue the different sequences, I made a remote control using XBEE modules so I can trigger each scene from the back. After talking with the play director I was given a thumbs up to go ahead with the idea.
    The time machine prop consisted of a wood frame on casters with a large flat front and an opening to see the kids that was built by another church member. The upper portion of the front was made large enough for a 17 inch LCD. After it was painted and some cosmetic props were added it was my turn to add the electronics.

    SEE ATTACHED SYSTEM DIAGRAM

    PARTS LIST: Propeller Board of Education, Parallax digital IO board, Altec Lansing powered subwoofer and speakers for computer, red, white, and blue LED strips from Parallax, several zip wire extension cables custom made, 2 12 volt power supplies, micro sd card with wave files, one surge protector, 17 inch LCD panel and driver board, laser cut wood mounts for LCD & boards, misc hardware: zip ties, zip tie mounts, screws, twisty ties…..two 12 volt muffin fans, XBEE module…remote control, Serpac enclosure hand held, Propeller mini XBEE module, 4x4 keypad membrane, 9v battery

    CODE Notes– earlier in this thread for key pad, several versions of time machine code, time machine counting thread, BST to optimize code due to memory space, trial run using laptop and XBEE, keypad issues and added resistors, final code clean up, review comments, comments about dead pin on board of education, making labels for remote control to match scene for play, making queue sheet for remote control

    PROTOTYPING: The code and circuit set up was done in a week and a half; mostly late evenings as usual for me. From the beginning, the code was developed on the Propeller Board of Education. (in the past, I would start with the PPDB and then move the project over to a final board.) This project required me to learn how to use the XBEE modules I got over a year ago. I used the Board of Education and an Activity Board along with my laptop/XBEE USB adaptor to do the remote control code. I was actually rather surprised how easy it was to use the XBEE modules (even though I bricked one of the five I have with the XCTU software; I set all of my modules to a new PAN ID and updated them to the latest firmware but in that process one of them did not survive the rewrite)
    Once I got the remote control code mostly working I started working on the VGA count down code. This became the biggest obstacle for me in this project. I started out with individual routines for each year that was to be jumped by the time machine so that the timing of the sound effects and the length of the countdown would match. By doing that, the code inflated rapidly and I ran out of memory. At first I looked for ways to optimize the objects used and started a post about it as well. After trying BST I was able to gain a lot of memory space but it still looked like I would run out again before I was done. I decided I’d have to dig a little deeper and have to figure out how to change my “playing timing” code into a reusable routine. After struggling with that for a while, I was able to get a routine that worked excellent and memory space was abundant.

    THE BUILD: Since I was using an LCD panel that was not in any kind of case, I needed some way to mount it to the time machine. I drew up spacers and retainers in MS Visio and cut them out of ¼ inch MDF with an Epilog Laser Cutter. The LCD was mounted on the upper portion of the front of the time machine. The control board for the LCD was placed on the back of the LCD panel with double sided foam tape. The cables ran to the left side then down to the propeller board of education. The 12v power for the LCD was routed through the opening then up with the other cables.
    The board of education and digital IO board were also mounted in the laser cut pieces on the lower portion of the front so that the LEDs on those boards would also be part of the prop. Mounting them behind the prop would have lessened the effect. (It is supposed to look like a time machine built by a church custodian.) A small hole was drilled on the front to route wires into the inside. The audio cable and power wires ran through this hole. To connect the Board of Education to the digital IO board, jumper wires were routed between the two and secured with a zip tie. We placed LED strips that had been cut to different links and had headers soldered on to them in various locations with the double sided tape that they came with. I had several zip wire extension cables made up so I could just plug one end into a led strip, route the wire to the digital IO board then cut and striped to proper length for the digital IO board. All of the positive ends for the LEDs were tied together to the 12 v supply and the negative ends were connected to the relays and the common points of all the relays were jumpered to ground. The two 12 v muffin fans were mounted on either side and wired to the digital IO board in the same way as the LEDs. The subwoofer was mounted on the inside on the bottom (literally; a screw through the corner was used to secure it in place). The two speakers were placed on the inside but up on the shelf by the opening. The speakers and other power supplies were plugged into a surge protector that was mounted to the rear side of the base.

    Once all of the electronics were on the time machine, some test code was used to make sure that everything worked together perfectly. At this time (midnight Friday night) it did not work perfectly but dress rehearsal was at 10 am Saturday, so we had to get home to rest up for that. I made a few changes to my code and felt everything should be ready for dress rehearsal.
    During dress rehearsal, the remote control was not triggering the appropriate events according the button pressed and its response seemed very random. For the dress rehearsal, I ended up using an XBEE module on a USB adaptor cord and sent the appropriate trigger codes using Parallax serial terminal. That worked perfectly so I knew the issue was with the remote control code. (insert details about keypad post) Other than sending a couple incorrect codes by accident, the time machine worked as expected so we were ready for the play (once I fixed the remote).
    Remote control fixing: details about assembly of remote control

    How did it go: The morning of the play the time machine was wheeled in to place and a couple test cycles ran through. Each trigger event was done in order to verify and the remote control and time machine worked perfect. (all I had to do was hit the right button at the right time now)
  • WBA ConsultingWBA Consulting Posts: 2,933
    edited 2017-11-16 21:38
    Reserved
  • Reserved for other
  • This was the final version of the code, finished at 2:14 AM the morning of the play. My notes are minimal in the code itself, but the code is not complex. Project Archive Zip is also attached.
    ' TIME MACHINE
    ' WBA Consulting
    ' Andrew Williams
    ' (c)2013
    '
    '  Code emulates a Time Machine Prop for a Church Christmas Kids Play.
    '  Uses WAV files for sound effects, drives a VGA display, and lights some LEDs
    '
    
    CON
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
        x_tiles = 16
        y_tiles = 12
    
    'WAV Player
        lPin = 26
        rPin = 27
    
        doPin = 22
        clkPin = 23
        diPin = 24
        csPin = 25
    
        wpPin = -1
        cdPin = -1
    
    VAR
      long  bitmap[3072+64] ' Must be aligned on 32 byte boundary
      long  colors[64]
      word  screen[x_tiles * y_tiles]
    
      long bitmapAddr
      byte numStr[5]
    
    OBJ
      vga   : "vga"
      gr    : "graphics"
      wav   : "V2-WAV_DACEngine.spin"
      xb    : "fullduplexserial"
    
    PUB start | DataIn
    
    'VGA Initilization
      StartVGA
    
    'WAV Player Initilization 
       wav.begin(lPin, rPin, doPin, clkPin, diPin, csPin, wpPin, cdPin)
    
    'xBee Initialization
      xb.start(16, 17, 0, 9600)           ' DO, DI, mode, baud
    
      dira[0..7]~~
      OUTA[0..7] := %11111100
    
    ' ~~~~~~~~~~~~~~~~~~~~
    
      WAITMS(2000)                     
      SYSREADY
    
    ' start of loop
     
      Repeat
        DataIn := XB.RxTime(3000)         ' Wait for byte with timeout
        If DataIn == "!"
           DataIn := XB.RxTime(3000)
           case DataIn
             "1" :
              JUMPYEAR(2013, 1978, 1, 300) 
             "2" :
              JUMPYEAR(1978, 1985, 1, 1500) 
             "3" :
              JUMPYEAR(1985, 1959, 1, 460)
             "4" :
              JUMPYEAR(1959, 1998, 1, 300)
             "5" :
              JUMPYEAR(1998, 1944, 1, 200)
             "6" :
              JUMPYEAR(1944, 0, 3, 18)
             "7" :
              JUMPYEAR(0, 1944, 3, 18)
             "8" :
              JUMPYEAR(1944, 2013, 1, 170)
             "9" :
               gr.clear
               sysready
             "0" :
              dataentry
    
           xb.rxflush                         'clear receive buffer
    
    PUB SYSREADY
    
      gr.textmode(3,3,6,5)
      gr.colorwidth(1,3)
      gr.text(-40,80,string("SYS READY"))
    
      gr.textmode(2,2,6,5)
      gr.colorwidth(2,2)
      gr.text(-70,-70,string("HO-2000"))
    
    PUB JUMPSTANDBY
    
      gr.clear
      gr.textmode(3,3,6,5)
      gr.colorwidth(1,3)
      gr.text(0,75,string("12 / 24"))
    
      gr.textmode(9,9,6,5)
      gr.colorwidth(1,3) 
      gr.text(0,10,string("----"))
    
      gr.textmode(2,2,6,5)
      gr.colorwidth(2,2)
      gr.text(-70,-70,string("HO-2000"))
     
      gr.textmode(2,2,6,5)
      gr.colorwidth(3, 2)
      gr.text(50, -70, string("12/24/----"))
    
    PUB DATAENTRY
    
        gr.clear
        SYSREADY
        wav.play(string("keys.wav"))  
        gr.textmode(4,4,6,0)
        gr.colorwidth(1,3) 
        gr.text(-70,10,string("#>1"))
        WAITMS(750)                                               
        gr.text(-70,10,string("#>12"))
        WAITMS(750)                                                   
    
        gr.clear
        SYSREADY
        gr.textmode(2,2,6,5)
        gr.colorwidth(3, 2)
        gr.text(50, -70, string("12/--/----"))
    
        gr.colorwidth(1,3)
        gr.textmode(4,4,6,0)
        WAITMS(250)                                                
        gr.text(-70,10,string("#>2"))
        WAITMS(250)                                               
        gr.text(-70,10,string("#>24"))
        WAITMS(750)                                                
        
        gr.clear
        SYSREADY
        gr.textmode(2,2,6,5)
        gr.colorwidth(3, 2)
        gr.text(50, -70, string("12/24/----"))
    
        gr.textmode(4,4,6,0)
        gr.colorwidth(1,3) 
        gr.text(-70,10,string("#> "))
    
    PUB Jumpyear(depyear, arryear, j, delayadj) | i
    
       wav.play(string("SFX.wav"))               ' Play 24 second long "time jump" sound effect
      WAITMS(2000)                               ' Let SFX get going
      JUMPSTANDBY                                ' Show time machine activation/standby display
      WAITMS(2000)                               ' and leave up for 2 seconds before counting
        
    ' Count from departure year to arrival year
    
       Repeat i from depyear to arryear step j
            num2str(i)
            OUTA[0..7] := %10101011
            gr.textmode(9,9,6,5)
            gr.colorwidth(1,3)
            gr.text(0,10,@numStr)
            WAITMS(delayadj)                                
            OUTA[0..7] := %11010111
            gr.colorwidth(0,8)
            gr.box(-120,-30,240,81)
    
       OUTA[0..7] := %11111110         
    ' Flash arrival (present) year
       repeat 8
          gr.colorwidth(0,8)
          gr.box(-120,-30,240,81)
          WAITMS(250)                                        
          gr.textmode(9,9,6,5)
          gr.colorwidth(1,8)
          num2str(arryear) 
          gr.text(0,10,@numStr)
          WAITMS(1000)
    
      OUTA[0..7] := %10001100                                          
    
    
     
    PUB num2str(value) | given ' For numbers from 100 to 9999
      given := value
      if value < 1000
        value *= 10
        
      numStr[0] := value / 1000  + "0"
      value //= 1000
      numStr[1] := value / 100 + "0"
      value //= 100
      numStr[2] := value / 10 + "0"
      value //= 10
      numStr[3] := value + "0"
      numStr[4] := 0
    
      if given < 1000
        numStr[3] := 0
    
    PUB StartVGA | i, dx, dy, c
    
      bitmapAddr := (@bitmap + $3F) & $FFFF_FFC0 ' Bitmap address must start on a 32 byte boundary 
    
      'start vga
      vga_videobase := @screen
      vga_colorbase := @colors
      vga.start(@vgaparams)
    
      'init colors
      repeat i from 0 to 63
        colors[i] := $28_48_FF_00 ' teal, purple, white, black
    
      'init tile screen
      repeat dx from 0 to vga_hc - 1
        repeat dy from 0 to vga_vc - 1
          screen[dy * vga_hc + dx] := bitmapAddr >> 6 + dy + dx * vga_vc         '+ ((dy & $3F) << 10)
    
      'start and setup graphics
      gr.start
      gr.setup(16, 12, 128, 96, bitmapAddr)
    
    
    PUB WAITMS(ms)  'wait time in milliseconds
       waitcnt(clkfreq / 1000 * mS + cnt) 
    
    DAT
    
    vgaparams               long    0               'status
                            long    1               'enable
                            long    %001_111        'pins
                            long    %0011           'mode
    vga_videobase           long    0               'videobase
    vga_colorbase           long    0               'colorbase
    vga_hc                  long    x_tiles         'hc
    vga_vc                  long    y_tiles         'vc
                            long    2               'hx        //RJA increased from 1X to 2X
                            long    2               'vx        //RJA increased from 1X to 2X 
                            long    0               'ho
                            long    0               'vo
                            long    512             'hd
                            long    16              'hf
                            long    96              'hs
                            long    48              'hb
                            long    380+16          'vd         //RJA added 16
                            long    11              'vf
                            long    2               'vs
                            long    31+16           'vb       //RJA subtracted 16
                            long    20_000_000      'rate
    
Sign In or Register to comment.