Shop OBEX P1 Docs P2 Docs Learn Events
Help with SPIN Code! - Progress Update for Spinneret Contest - An RFID Access System — Parallax Forums

Help with SPIN Code! - Progress Update for Spinneret Contest - An RFID Access System

lazer lukelazer luke Posts: 27
edited 2011-06-08 23:21 in Accessories
Greetings,

So here is the current code from our RFID access development project and Spinneret competition submission. I need some more help and advice with the SPIN code. This is my first Spinneret (and Propeller) project. I have both the Propeller Manual and Programming and Customizing the Multicore Propeller Micro-controller and they have been great for getting the ball rolling. So far I think it is going well. Although I do need some help moving on from this current iteration.

Just to recap a few things about the status of and conditions surrounding this project. I am a member an instructor at the 3rd Ward Incubator for Innovation in Brooklyn http://www.3rdward.com/ . We are developing an RFID door access system for the shop and studio doors and ultimately some of the shop equipment. Below (before the code) I have some more details about the development and a Road-map to finishing it. I need to have a working networked prototype by this Friday and finished install by the first of July.

What the system does is: take the scanned the RFID card data and via a POST command submit it to a Filemaker based system. That query returns either a 1 or a 0 and the door ether opens or it doesn't. The parts of the hardware circuit are working. Each part of the system has been tested independently with simple test programs. This is the current progress with putting the pieces together.


Mike G pointed out that I should be using memory locks. Thanks.

So this afternoon I reworked the code. I am not sure if I have implemented the memory locks correctly. Also, I am curious if my usage of cognew is correct. I was getting a compile error when trying to use the included parameter list. I switched from using Parameterlist to adding another locked variable to the memory lock routine.
Is this alright. Is it better for some reason to have the variables go through the cognew ParameterList vs managing that with memory locks?

Other questions and concerns that have arisen:

I am setting the pin that triggers the Door Strike to LOW as part of the initialization. Is that necessary?

Do I need to specify that the program waits for each step in the DHCPClient routine in the ServeComMode method? OR is that innate in using the drivers? (I guess I should implement some kind of time out if the server doesn't respond)

I noticed that the RFID module resets from the card read mode to just normal powered up mode after about 25 seconds. So I need to resend that command periodically. That is why I have a waitcnt at the end of the Listen Mode Loop. Is this the best way to achieve this?

During the Listen Mode Loop - if the card is scanned I want to set the variable cardread (read as "card read" and not "car dread") to 1. Does the if Result <> 0 in the Listen Mode Loop achieve that?

Do I need to Stop (or should I) either the Door Access Mode and Listen Mode Loop methods?


Please point out any other issues that you may notice. I am knuckling down to meet this Friday deadline; So thanks in advance for your feed back.


Networked RFID Door and Equipment Access System

Development Road-map for RFID Access System

Phase 1 - Completed May 2011

A Stand Alone Un-Networked RFID Card system for access to Think Tank and Media Lab @ The 3rd Ward Incubator for Innovation.
DSC_0246.jpg
DSC_0245.jpg


Built using an Arduino Decimia, a handmade Proto Sheild (made by Kimio Kosaka), Sparkfun Relay Board,
Parallax and Grand Design Studios RFID Read and Write Module and an existing preinstalled 12 Volt
Door Strike and a door bell style button. The system is enclosed in a series of enclosures custom built on a Makerbot
Thingomatic.

This first prototype system is installed in the Lobby's Think Tank Door @ The 3rd Ward. It has been working with uninterrupted service for approximately one month.
It will be replaced by the Phase 2 iteration of the system which is based on the Parallax Spineret Web Server.


Phase 2 - Deadline June 10, 2011
DSC_0248.jpg

A Networked RFID Door Access Node that is integrated with the networked database and member system.

Built using the Parallax Spinneret Module, Proto Daughter board, Parallax and Grand Design Studios RFID Read and Write Module,
Sparkfun Relay Board, 12 volt door strike and door bell style button.


Phase 3 - Deadline July 1, 2011

Installation of 3 Networked RFID Nodes into The 3rd Ward Incubator for Innovation

Will be very similar to the Phase 2 version but will contain indicator lights and redesigned enclosures.

Phase 4 - 2012

Module based on the RFID Door Access System that can be retrofitted into a variety of Shop Tools, other equipment, computers and cabinets.


Technical Specifications and Code

Based on the following drivers and code examples:

Easy WebServer DEMO2 (build 01_28_2011) v1

RFID RFID Read/Write Object Wrapper

WIZnet W5100 SPI Driver Ver. 00.14
}}
CON
        _clkfreq = 80_000_000
        _clkmode = xtal1 + pll16x
    
        socket = 0
        listenPort = 80

        RFID_TX              = 25   ' Connects to RFID R/W Module SIN
        RFID_RX              = 26   ' Connects to RFID R/W Module SOUT
OBJ
        DHCPClient    : "DHCP_GBSbuild_01_28_2011.spin"
        RTC           : "s-35390A_GBSbuild_01_23_2011"
        PST           : "Parallax Serial Terminal"
        Host          : "FullDuplexSerial"
        RFID          : "RFID.Reader.Writer.Driver"

VAR
        long  IP, SubnetMask, GatewayIP, DNS_Server ,destIP
        byte  MAC_Address[6], data[DHCPClient#BUFFER_SIZE]

VAR

        byte TestBuffer[ 12 ]
        byte CardDataBuffer[ 32 * 4 ]
        byte OldPwdBuffer[ 4 ]
        byte NewPwdBuffer[ 4 ]
        byte HostDataBuffer[ 10 ]

        long scsstack[ 6 ]
        byte token[ 4 ]
        byte access[ 1 ]

        long lml [ 128 ]        'stack for cog listen mode loop - set to 128 per Prop manual - Page 80
        long dam [ 128 ]        'stack for cog door access mode

        byte AccessLockID
        byte CardDataBufferLock
        byte cardread [ 1 ]
VAR
        'byte  ButtonSelected
        'byte  Stringbuffer[100]

PUB Intializer

'Initialize Wiznet 5100 chip
    DHCPClient.Wiznet5100(socket, @MAC_Address, @GatewayIP, @SubnetMask, @IP, @destIP, listenPort)

    RTC.start                   'Initialize On board RTC XXXXXX This was from the webserver demo.  Mabye I don't need it.  Unless it would be
                                'usefull for calculating time in seconds.  Should this possibly happen earlier in the program?

  ' RTC.SetDateTime(month, day, year, dayOfWeek, hour, minutes, seconds) '<- Just do this once to set time


                                                        '2.1 - Open Socket to web server

    PST.start(115200)             'Initialize Parallax Serial Terminal

  ' Network Settings
    DHCPClient.IPs(@IP,192,168,1,110)                      ' IP ; a static address of the router
    DHCPClient.IPs(@SubnetMask,255,255,255,255)             ' SubnetMask ; see: www.subnet-calculator.com
    DHCPClient.IPs(@GatewayIP,192,168,1,10)                ' GatewayIP ; your local router's address
    DHCPClient.IPs(@DNS_Server,192,168,1,10)               ' DNS_Server ; usually same as Gateway
    DHCPClient.IPs(@destIP,0,0,0,0)                       ' Dest IP can be all zero's
    DHCPClient.MAC(@MAC_Address,$00,$08,$DC,$16,$F1,$3C)  ' MAC address located on spinneret

    RFID.Start( RFID_RX, RFID_TX ) 'Start Serial to RFID R/W Module

'Do I need to set this low?  Since by default the Pin Will be low.  What is the best practice?
    DIRA[24]  := 0                                     'Pin 24 Low - Door Lock State
    OUTA[24]  := 0

    cardread := 0

PUB ServerComMode

  cognew (ListenModeLoop, @lml)
  cognew (DoorAccessMode, @dam )

  'locknew
  if (CardDataBuffer := locknew) == -1
    '<error no locks availible>
  else

  if (access := locknew) == -1
    '<error no locks availible>
  else

  if (cardread := locknew) == -1
    '<error no locks availible>
  else




  ' Infinite loop of the server ; listen on the TCP socket
   'CardBufferData :=1           'This line was in the example I started with.
  repeat
    if @cardread := 1

      'DHCPClient.HTMLReady(@data)==0                   'Is connection ready to send HTML?
                                                        'Thinking this could and should be changed
                                                         'to check if the card data buffer is loaded?

         'PST.Char(0)
        ' PST.str(@data)
         'ParseDATA(@x)      '

                                                                '2.2 - TX - HTTP POST - Request Session Tolken
      DHCPClient.StringSend(socket, @TokenRequestHeader)




                                                                '2.3 - RX - Recive Session Token

      DHCPClient.rxTCP(socket, @token)


                                                                '2.4 - Tolken and RFID Data Buffers. Combine or send sequentially?
                                                                'This might not need to exist as when AccessRequestHeader is called
                                                                'it will just be taken care of in the POST.

'combine into a string or just as POST elements@token, @CardBufferData



                                                                '2.5 - TX - HTTP POST - Send Token and RFID Data



      DHCPClient.StringSend(socket, @AccessRequestHeader)



                                                                '2.6 - RX - Recieve Server respose and stores it in buffer


      DHCPClient.rxTCP(socket, @access)



                                                                 '2.7 - Close Socket connection


      DHCPClient.NoPersistanceAllowed(socket)





PUB ListenModeLoop  '| ErrCheck, CmdByte, LoopCounter, IndexCounter, Offset                  LISTEN MODE LOOP
Repeat

  Repeat until not lockset(CardDataBuffer)
    lockclr (CardDataBuffer)

  Repeat until not lockset(cardread)
    lockclr (cardread)
                                                          '
'pub startRFIDread
  'REPEAT 'until @TestDataBuffer <> 1
                                                        '1.3 - Send RFID R/W module Hexadeciamal Read command 0X01

        'Host.str( string( "Trying to read all card data...", 13 ) )
        bytefill( @CardDataBuffer, 0, 128 )
        Result := RFID.TryToReadCardData( @CardDataBuffer, 0, 32, 5 )
        if Result <> 0
          cardread := 1
        'waitcnt ( 50_00_000 + cnt ) 



waitcnt ( 1_600_000_000 + cnt )

PUB DoorAccessMode
Repeat until not lockset(access)
    lockclr (access)

if @access := 1                  '3.1.2 - Server responded 1

    'DIRA[??]  := 1              '3.1.2.1 - Access Granted Indicator LED
    'OUTA[??]  := 1


    DIRA[24]  := 1              '3.1.2.2 - Door Strike Unlock - PIN 24 High
    OUTA[24]  := 1

    waitcnt ( 400_000_000 + cnt )                       '3.1.2.3 - Wait 5 Seconds


    'DIRA[??]  := 0              '3.1.2.1 - Access Granted Indicator LED
    'OUTA[??]  := 0


    DIRA[24]  := 0              '3.1.2.2 - Door Strike Unlock - PIN 24 High
    OUTA[24]  := 0


                                '3.1.2.4 - Start Listen Mode Loop







if @access := 0                 '3.1.1 - Sever reponded 0 This is commented out but ultimatley it will bw


  'DIRA[??]  := 1                '3.1.1.1 - Access Deined Indicator LED -
                                'Commented out for now as the LED part of the circuit
                                'will be implemented in next version.
  'OUTA[??]  := 1
  'waitcnt ( 20_000_000 + cnt )



    'listenMODEloop.start
    'or
    'cognew

DAT


TokenRequestHeader

        byte "<POST / HTTP/1.1>"
        byte "< Host: 192.168.1.1>"
        byte "<Connection: close>"
        byte "<User-Agent: Web-sniffer/1.0.37 (+http://web-sniffer.net/)>"
        byte "<Accept-Encoding: gzip>"
        byte "<Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7>"
        byte "<Cache-Control: no-cache>"
        byte "<Accept-Language: de,en;q=0.7,en-us;q=0.3>"
        byte "<Referer: http://web-sniffer.net/>"
        byte "<Content-type: application/x-www-form-urlencoded>"
        byte "<Content-length: 1>"
        byte "<Tokenreqyest: (@tokenrequest)>"


AccessRequestHeader

        byte "<POST / HTTP/1.1>"
        byte "< Host: 192.168.1.1>"
        byte "<Connection: close>"
        byte "<User-Agent: Web-sniffer/1.0.37 (+http://web-sniffer.net/)>"
        byte "<Accept-Encoding: gzip>"
        byte "<Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7>"
        byte "<Cache-Control: no-cache>"
        byte "<Accept-Language: de,en;q=0.7,en-us;q=0.3>"
        byte "<Referer: http://web-sniffer.net/>"
        byte "<Content-type: application/x-www-form-urlencoded>"
        byte "<Content-length: 34>"
        byte "<Token: (@token)>"
        byte "<RFID Data: (@CardBufferData)>"



OBJ
{{


&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
&#9474;                                     TERMS OF USE: MIT License                                     &#9474;                                                            
&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
&#9474;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and  &#9474;
&#9474;associated documentation files (the "Software"), to deal in the Software without restriction,      &#9474;
&#9474;including without limitation the rights to use, copy, modify, merge, publish, distribute,          &#9474;
&#9474;sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is      &#9474;
&#9474;furnished to do so, subject to the following conditions:                                           &#9474;
&#9474;                                                                                                   &#9474;
&#9474;The above copyright notice and this permission notice shall be included in all copies or           &#9474;
&#9474; substantial portions of the Software.                                                             &#9474;
&#9474;                                                                                                   &#9474;
&#9474;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT  &#9474;
&#9474;NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND             &#9474;
&#9474;NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,       &#9474;
&#9474;DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,                   &#9474;
&#9474;ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE        &#9474;
&#9474;SOFTWARE.                                                                                          &#9474;     
&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
}} 
1024 x 680 - 83K
1024 x 680 - 114K
1024 x 680 - 98K

Comments

  • Mike GMike G Posts: 2,702
    edited 2011-06-08 20:03
    @lazer luke, First off your code does not compile. Line 98 is the first of several errors found by the Spin Tool.
        if @cardread := 1
    
    The "@" returns the address of the symbol "cardread". The statement @cardread := 1 is like the saying; assign the number 1 to the number 123. I think you want if cardread[0] == 1 or if byte[@cardread] == 1. See page 173 in the Propeller Manual.


    DHCPClient.Wiznet5100(...) is invoked before the argument list is filled with data. The web server is not initialized properly.
      DHCPClient.Wiznet5100(socket, @MAC_Address, @GatewayIP, @SubnetMask, @IP, @destIP, listenPort) 
    ...
       DHCPClient.IPs(@IP,192,168,1,110)                      ' IP ; a static address of the router
        DHCPClient.IPs(@SubnetMask,255,255,255,255)             ' SubnetMask ; see: www.subnet-calculator.com
        DHCPClient.IPs(@GatewayIP,192,168,1,10)                ' GatewayIP ; your local router's address
        DHCPClient.IPs(@DNS_Server,192,168,1,10)               ' DNS_Server ; usually same as Gateway
        DHCPClient.IPs(@destIP,0,0,0,0)                       ' Dest IP can be all zero's
        DHCPClient.MAC(@MAC_Address,$00,$08,$DC,$16,$F1,$3C)  ' MAC address located on spinneret
    

    PUB Intializer is the application entry point. Intializer does not call any other methods. When you reach the end of Intializer, your program stops; ServerComMode is never called. Chapters 5 and 6 in the PE kit covers methods and COGs. You can find the PE kit in the Spin Tool Help dropdown menu.

    The use of memory locks is way off. The idea is to allow only one process to access memory at one time. A memory lock is either in the locked or unlocked state. Processes are not allowed to touch memory that is in a locked state. Read pages 120, 122, 125, and 126 in the Propeller Manual.
  • lazer lukelazer luke Posts: 27
    edited 2011-06-08 23:21
    Th@nks for the quick reply. I know some of what I am putting out is a hot mess. But time frames and deadlines being what they are; I needed to post where I was at the end of the work session. Or ..... I would not even have a chance to finish in time.

    Honestly I wasn't sure about the @ beginning of those variables. I am really piecing this together from a medley of sources and and that is what happened along the way. I cut the extraneous @.

    As for cardread. I think I got what you meant with regard to the it not being the same as 123 and the @ address vs the actual variable. (after awhile it all just looks like pixels)

    But to clarify what cardread was supposed to be and do. Cardread is not the actual card value just a 1 or 0. Indicating if the CardDataBuffer had data or not. I was thinking that the following line would be the real problem.
    if Result <> 0
              cardread := 1
    
    I am not sure comparison of the Result to 0 would be a legitimate comparison.

    So the idea for cardread would be set to 0 in Initialization and then 1 when the CardDataBuffer was filled. I realize now ...... I never set it back to zero after DoorAccessMode. Making note.

    OK. I see the initialization and the variables in the web-server were out of order. How did that happen? Oh yeah I did it.

    With regards to the locks. I read over those pages and instances of memory lock in the forum. I get the concept of how the locks work and why to use them. But have yet to really digest how to incorporate them. Going to look at it with fresh eyes in the morning!

    Thanks again for the feedback. Will be working on it again tomorrow and updating as circumstances progress.

    Luke
Sign In or Register to comment.