Create a connected PIR sensor with SigFox

Pir sensor

Pir sensor

In a previous blog post I described how I built a PIR sensor connected to Internet, based on the use of a Raspberry Pi device. As you can read in this previous post, the solution have a certain number of complexities like requiring a power supply, a 3G modem …

As it was originally planed to be done, here is the design of the same product, based on a SigFox device. This is really interesting to demonstrate the differences and the advantages of this technology. Let’s review how to built it !

 

Let’s take a look to the hardware part

SigFox TD1208 as a connected PIR sensor

SigFox TD1208 as a connected PIR sensor

The first thing to notice on the picture is the power supply provided by two batteries. Then the simplicity of the design have also to be noticed : 1 chip, 1 antenna and a couple of wires. The price of the design is as a consequence lower and the reliability higher.

Let’s have a look to the software part

The software part is different, as the platform does not run something like a Linux OS, developing with SigFox means developing with a micro-controller, like for an arduino. The TD1208 chip is containing a ARM Cortex M3 processor and it is possible to upload a home built firmware. To create the PIR function, here is the code I customized from the modem example :

As for Arduino, the first thing is to do the setup. The first thing is to create an Interrupt callback on the PIR events, the second thing is to create a Sched to proceed the transmission. This method sounded like the more easy to do in the existing code

#define PIR_PORT    USR0_PORT                /**< PIR port */
#define PIR_BIT     USR0_BIT                 /**< PIR bit */
#define PIR_MASK    USR0_MASK                /**< PIR mask */
void TD_USER_Setup(void)
{
   // ...

   // *** My custom code
   AT_printf("Startup!");
   int type;
   IRQn_Type irq_parity;

   // Configure the PIR wire as an input
   GPIO_PinModeSet(PIR_PORT, PIR_BIT, gpioModeInputPull, 1);
   // Configure an interrupt on Pire wire
   type = (PIR_MASK & TD_GPIO_ODD_MASK) ?
           TD_GPIO_USER_ODD : TD_GPIO_USER_EVEN;
   TD_GPIO_SetCallback(type, PIRInterrupt, PIR_MASK);
   // Enable rising & falling edge interrupts on button pin
   GPIO_IntConfig(PIR_PORT, PIR_BIT, true, true, true);

   // Clear and enable the corresponding interrupt in the CPU's Nested Vector
   // Interrupt Controller
   irq_parity =
               (PIR_MASK & TD_GPIO_ODD_MASK) ? GPIO_ODD_IRQn : GPIO_EVEN_IRQn;
   NVIC_ClearPendingIRQ(irq_parity);
   NVIC_EnableIRQ(irq_parity);


    // Initialize the timer to generate IRQs
    // temps passé en seconde (premier arg ou tick de 1/32k
    myCycleCounter = 14;
    myTimer = TD_SCHEDULER_AppendIrq(20, 0 , 0, TD_SCHEDULER_INFINITE, mySched, 0);
}

The next part concerns the Interrupt callback: The objective is to detect and store if the PIR has been activated during the sched sleep period.

static void PIRInterrupt(uint32_t mask)
{
    if (GPIO_PinInGet(PIR_PORT, PIR_BIT) == 0) {
      if ( PIRstate == PIR_ST_UNKNOWN )
         PIRstate = PIR_ST_NOTACTIV;
    } else {
        PIRstate = PIR_ST_ACTIV;
    }
    PIRevent = true;
}

Now here is the sched code : This function is automatically called after 20 seconds, but we are processing data only every 15 iterations to limit a transmit rate every 5 minutes. This is a small sleep time in fact as we are limited to 140 frame sent per days, so normally the stand-by time should be about 10 minutes. One interesting thing to consider also is that the time reference is not reliable and in my test, shorter than expected. So I would recommend a sleep period from 12 to 15 minutes to ensure the message rate limit.

static void mySched(uint32_t arg, uint8_t repetition)
{
    if ( myCycleCounter == 15 ) {
        myCycleCounter = 0;

        unsigned int temp = TD_MEASURE_VoltageTemperatureExtended(true);
        unsigned int volt = TD_MEASURE_VoltageTemperatureExtended(false);
        unsigned int lum = 4096 - getLuminosity(6);
        uint8_t message[12];
        message[0] = (PIRstate==PIR_ST_ACTIV)?0x01:0x00;
        message[1] = 0x00;
        message[2] = ( temp >> 8 ) & 0xff;
        message[3] = ( temp ) & 0xff;
        message[4] = ( volt >> 8 ) & 0xff;
        message[5] = ( volt ) & 0xff;
        message[6] = ( lum >> 8 ) & 0xff;
        message[7] = ( lum ) & 0xff;
        message[8] = 0x00;
        message[9] = 0x00;
        message[10] = 0x00;
        message[11] = 0x00;
        sprintf(_smess,"AT$SS=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
                      message[0], message[1], message[2], message[3],
                      message[4], message[5], message[6], message[7],
                      message[8], message[9], message[10], message[11]);
        AT_printf("%s",_smess);
        sendMess = 0;
        if ( PIRevent ) {
            sendMess = 1;
        } else {
            if ( PIRlastSent != -1 && PIRlastSent != PIRstate ) {
                sendMess = 1;
            }
            // 30 minutes - force a message update to get temperature ...
            if ( myLongCycleCounter >= 6 ) {
                myLongCycleCounter = 0;
                sendMess = 1;
            }
            myLongCycleCounter++;
        }
        if ( sendMess == 1 ) {
               myLongCycleCounter = 0;
               PIRlastSent = PIRstate;
        }

        PIRevent = false;
        PIRstate = PIR_ST_NOTACTIV;
    } 
    myCycleCounter++;
}

Normally, this procedure should send the message over the SigFox network. But unfortunately the call to the ad-hoc procedure is failing and reseting the device. For this reason I had to write some bad code in the main loop …

void TD_USER_Loop(void)
{
    int c;
    // ...
    if (sendMess == 1) {
       GPIO_PinOutSet(LED_PORT,LED_BIT);
       int i;
       for ( i = 0 ; i < strlen(_smess) ;i++) {
           AT_Parse((int)_smess[i]);
       }
       GPIO_PinOutClear(LED_PORT,LED_BIT);
       sendMess = 0;
    }
}

This is not optimal but works… I’m sure we can do better by removing the sched and proceed in the main loop but it needed some investigation on loop period I did not had time to do.. By-the-way, this is to illustrate how to do a such project.

To finish, now let’s have a look to the back-end

As described in some previous post, the back-end is a simple php page receiving a callback from the SigFox network with the message sent as parameter. The message has to be extract to get back the values :

<html>
  <head>
   <title>Demonstrateur SigFox</title>
  </head>
  <body>
  <?php 
     $_data = $_GET["data"];
     $_avgSignal = $_GET["avgSignal"];
     $_presence = intval($_data[0] . $_data[1], 16);
     $_temp = intval($_data[4] . $_data[5] . $_data[6] . $_data[7], 16);
     $_volt = intval($_data[8] . $_data[9] . $_data[10] . $_data[11], 16);
     $_lum = intval($_data[12] . $_data[13] . $_data[14] . $_data[15], 16);
  ?>
  </body>
</html>

To conclude

In my point of view the main point to retain is that to build a PIR solution based on a SigFox device is a little bit more complicated, because you need to solder some wires and write a real peace of code to make it working. But basically this is our job to do that. And compared to the RPI solution, this is a real industrial solution with an affordable cost.

 

14 thoughts on “Create a connected PIR sensor with SigFox

      • Bonjour,

        J’ai un problème lors du build sur Eclipse:
        “Error: Program “arm-none-eabi-gcc” not found in PATH”
        En recherchant des solutions des google, on nous dit qu’on doit doit rêgler le chemin d’accès du compilateur sur l’onglet “Toolchains” dans “settings”. Mais c’est un onglet qui n’apparait pas sur la version d’Eclipse donné par Telecom Design.
        Comment rêgler ce problème sachant que tout se trouve apparamment ici: “C:\TD\TD_RF_Module_SDK-v4.0.0\gnu\arm-none-eabi\bin”?

        Merci pour votre aide.

      • Take a look to my post of the SDK, I think you will find the right process to make to working.

      • I’ve already checked this article out. I didn’t find any solution for my problem. Do I have to fix something in the project properties?

      • All what I’ve done is described in the post. That said, I fighted a lot with compilation and I still have issues with includes working on compilation but not in the editor … by-the-way as I wrote in my post, to solve it, I added the compiler in the PATH

        “Go to Window System Properties >> Advance panel >> Environment Variable. Then add to your PATH list : C:\TD\TD_RF_Module_SDK-v4.0.0\gnu\bin;C:\TD\TD_RF_Module_SDK-v4.0.0\gnu\arm-none-eabi\bin”

        You should try it if not yet done.

  1. Hi Paul,

    Well done ! Thank you for the topic. I love the way Sigfox and Telecom Design are building the Internet of Things.

    I wondered how you did in order to upload your custom code inside the TD1208. I used to play with it through the set of AT commands, I didn’t know it could store and run the host application. I read the datasheet as well as the reference manual but did’nt find any instruction about that.

    Thanks!

    Jean-Philippe

  2. Have you tried to connect multiple PIR sensor on your device TD1208 indeed I tried and the callback is not working. This seems to come from function TD_GPIO_SetCallback (type1, PIRInterrupt1, PIR1_MASK); which does not appear in the array of callback in the Telecom design lib Core. It is a bug in the TD lib_core or me … if you can test for feedback. I would be very grateful

    • I did not tried to use multiple interrupt source, by-the-way, eventually you can use a OR gate between the different PIR sensor if this is what you want to do.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>