Menu

Christmas lights automation

Peter
2014-12-14
2015-01-01
  • Peter

    Peter - 2014-12-14

    I've finally got a PIC to do something useful!

    I'm posting the code here because it might have some bits and pieces which will be useful to others - I'm not submitting it for inclusion in a future release.

    The code is basically a home automation controller using some cheap remote control sockets I got from a supermarket a few years ago. Requires a PIC, a RTC (I've used the MCP7940N but a DS1307 would work) and an FM transmitter module on PORTD.1 .

    The code is pasted below, the MCP7940N library file is attached at the bottom and there's an epic demonstration video. Merry Christmas!

    ;Chip Settings
    #chip 16F914,8
    #config CP=OFF, MCLRE=OFF, PWRTE=ON, WDT=OFF, OSC=INTRC_OSC_NOCLKOUT
    
    ;Include files (Libraries)
    #include <MCP7940N.h>
    
    ;Defines (Constants)
    #define LCD_IO 8
    #define LCD_RW PORTD.6
    #define LCD_RS PORTD.7
    #define LCD_Enable PORTD.5
    #define LCD_DATA_PORT PORTA
    #define I2C_MODE Master
    #define I2C_DISABLE_INTERRUPTS ON
    #define I2C_DATA PORTC.7
    #define I2C_CLOCK PORTC.6
    
    ;Defines (Constants)
    #define TX_Period = 74         'Half length of the clock cycle in 10 microseconds.  This must be an even number.
    #define TX_Repeat = 94         'Delay between resending signal in miliseconds
    
    ;Variables
    Dim hr As byte                 'Hour
    Dim mn As byte                 'Minute
    Dim sc As byte                 'Seconds
    Dim am As byte                 'AM/PM
    
    Dim lights as Byte             'Current status of the lights
    lights = 255
    
    'Set the time
    MCP7940_SetTime 19, 14, 30     'Initial clock setting.  RTC will remember time as long as it has power.
    MCP7940_Enable 255             'Enable the RTC
    CLS
    Do Forever
        Locate 0, 0
        Print "           "
        Locate 0, 0
        DisplayTime
              Locate 1, 0
              Print "Lights "
              If lights = 0 then
                 Print "OFF"
              Else
                 Print "ON "
              End If
    
        Wait 500 ms
              CheckTime
    
    Loop
    END
    
    Sub CheckTime
    
      'Polls the time and decides whether an event has occurred
      'In this case, set a variable to 255 at 16:00:00 and to 0 at 22:00:00
          If lights = 0 Then   'lights are off
             'Turn on when it gets to 4 PM
             If hr = 16 then
                lights = 255
                CLS
                Print "Turning on..."
                CMD_ON1
             End If
          Else                'lights are on
              'Turn on when it gets to 10 PM
             If hr = 22 then
                CLS
                Print "Turning off..."
                lights = 0
                CMD_OFF1
             End If
          End If
    
    End Sub
    
    Sub DisplayTime
        'MCP7940_ReadClock hr, mn, sc, am, day, dd, mm, yy
              MCP7940_ReadTime hr, mn, sc, am
        Print hr
        Locate 0, 2
        Print ":"
        Locate 0, 3
        Print mn
        Locate 0, 5
        Print ":"
        Locate 0, 6
        Print sc
        Locate 0, 10
        If am = 0 Then
            Print "AM"
        Else
            Print "PM"
        End If
    End Sub
    
    Sub CMD_ON1()
    
        Set PORTC.2 On
    
        For j = 1 to 5                    'send signal 5 times
    
          For i = 1 to 24                  'read 24 values from the system data table
            ReadTable SYSTEM, i, code
            sendpulse(code)
          Next
    
          For i = 1 to 18                 'read first 7 values from the command data table
            ReadTable ON_1, i, code
            sendpulse(code)
          Next
    
          Wait TX_Repeat ms
        Next
    
        Set PORTC.2 Off
    
    End Sub
    
    Sub CMD_OFF1()
    
        Set PORTC.2 On
    
        For j = 1 to 5                    'send signal 5 times
    
          For i = 1 to 24                  'read 24 values from the system data table
            ReadTable SYSTEM, i, code
            sendpulse(code)
          Next
    
          For i = 1 to 18                 'read first 7 values from the command data table
            ReadTable OFF_1, i, code
            sendpulse(code)
          Next
    
          Wait TX_Repeat ms
        Next
    
        Set PORTC.2 Off
    
    End Sub
    
    
    Sub SendPulse (In duration)
        'toggle the pulse for a set number of cycles
        if lat = 1 then
            lat = 0
            set PORTD.1 = Off
        else
            lat = 1
            set PORTD.1 = On
        end if
        wait TX_Period * (duration+1) 10us
    End Sub
    
    Table SYSTEM
    0
    1
    0
    0
    1
    1
    0
    1
    0
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    End Table
    Table ON_1
    1
    0
    1
    0
    1
    0
    1
    1
    0
    0
    1
    0
    1
    0
    1
    1
    0
    1
    End Table
    Table OFF_1
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    End Table
    
     
  • Peter

    Peter - 2014-12-14

    Here's the MCP7940N.h that is needed for the above code.

     
  • Anobium

    Anobium - 2014-12-15

    Nice job. Thanks for sharing.

     
  • Keith

    Keith - 2014-12-15

    Yes, I would say it is useful particularly how you have tied two of my pet topics together. Time and I2C Bus interfacing (I never seem to be able to get that to work without a struggle!) and those cheapie Remote Control Power outlets.

    Could I bother you for a schematic please? I find I can follow things more easily from a drawing. Thank you for sharing your project.

     
  • Keith

    Keith - 2014-12-15

    Another Question. How are you managing to analysis the Data Out from the receiver in Audacity? Are you taking it in as an audio Signal? or are you using a digital oscilloscope?

     
  • Peter

    Peter - 2014-12-16

    Keith,

    I'll knock up a schematic sometime soon and post it on here. There's nothing too complicated with the layout/components.

    The RF signal is read as an audio signal using a 'souund card oscilloscope' (a couple of resistors and a 3.5mm jack). The left/right channel is connected to an RF receiver and the 'ground' is connected to 0V. More details here: http://rayshobby.net/?p=3381

    A lot of the project is a bodge in one way or another. The main examples are:

    • The RF signal seems to be Manchester Code but I struggled to decode it properly so stored it as a long-pulse:short-pulse sequence (1 and 2 instead of 0 and 1).
    • The RTC includes an alarm which will set a pin high which can be used for interrupts but I couldn't get interrupts to work properly or the alarm to trigger properly. Instead I poll the RTC for the time every 500 ms and see if it matches the condition.
     
  • Keith

    Keith - 2014-12-16

    Peter,
    Yes I think you are right, most of the coding in these things is Manchester, or at least a flavour of it. I have played around with Keelog RF600 Encoder/Decoders a lot which uses the same coding.

    To be honest, I buy those RF Kits from boot sales for thre’pence and five Woodbines or of FleaBay take them home, whip the guts out and bin them, then put my own RC Kit into the plastic enclosures – Great Fun, making something useful and reliable from Chinese crap…

    Thanks for the info on the Audacity wrinkle, can’t wait to try it out. As to the schematic, it doesn’t have to all singing and dancing, I’ve become quite used to deciphering stuff scribbled on a wet beer mat or a fag packet…

     
  • Peter

    Peter - 2014-12-17

    Rough schematic attached.

    If it's not clear, the crystal/capacitor layout is as per the datasheet for the MCP7940N. Use 100k pullups on the I2C line (82k worked too).
    The RF transmitter is by quasar. It also works with a smaller, nicer one I got off eBay. I can't remember if it's AM or FM.

    Good luck experimenting. It takes a bit of trial and error to get it working.

     
  • Anobium

    Anobium - 2015-01-01

    @Peter.

    I have finally got some sample MSP7940N delivered. I have updated your .h file to cover the full set of functionality for the device.

    Do you have some time for some quick tests?

    Quick Command Reference:

    MCP7940_EnableOscillator(flag [true|false])            ; 
    MCP7940_BatteryBackup(flag [true|false])
    MCP7940_ClearPowerFail
    MCP7940_PowerFailStatus. This function return true or false, You can then read the date information for failures.
    MCP7940_ResetClock
    MCP7940_SetClock(hour, minute, second, DOW, date, month, year)
    MCP7940_SetTime(hour, minute, second)
    MCP7940_SetDate(DOW, date, month, year)
    MCP7940_ReadClock(hour, minute, second, a.m.|p.m., DOW, date, month, year)
    MCP7940_ReadTime(hour, minute, second, a.m.|p.m.)
    MCP7940_ReadDate(DOW, date, month, year)
    MCP7940_SetHourMode(12|24)
    MCP7940_ReadHourMode(12|24)
    MCP7940_SetSQW(rate)
    MCP7940_SetMFP(True | False OR On | Off)
    MCP7940_SetControl(value)
    MCP7940_ReadControl. A function return currrent value
    MCP7940_Write(address, value)
    MCP7940_Read(address, value)
    MCP7940_SetAlarm ( [0 |  1] , hour, minute, second, DOW, date )
    MCP7940_SetAlarmMask ( [0 |  1] , alarmAssertionMatch )
    MCP7940_ReadAlarm ( [0 |  1] , hour, minute, second, DOW, date ). Return values
    MCP7940_ClearAlarm ( [0 |  1] )
    MCP7940_AlarmStatus ( [0 |  1] )
    MCP7940_SetAlarmPolarity ( On | Off )
    MCP7940_EnableAlarm ( [0 |  1] )
    MCP7940_DisableAlarm ( [0 |  1] )
    
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.