Introduction: Make a Secret IR-camera Security Raspberry Pi Unit

About: I like to explore new things and try out stuff. At the moment I'm in to electronics, BLE and LEDs.

Did you ever wanted to know what's going on in your room, when you're not at home?

Did you ever wanted to know who's entering your room and grubbing around in your things?

Did you want to have a robot friend you can send messages and who would answer?

So then I got news for you: It can be done with a raspberry pi and only a few extra parts!

Come on let's do it!

Don't be afraid of the many steps. Some you can skip, others are information only. This is no a to z receipe, but a list of hints what can be done and how!

Step 1: Gather the Parts

What do you need: (with the prices I paid)

  • Raspberry pi B or B+ or 2 (35.- €)
  • at least a 8GB SD-Card (lot space for pictures...) (5.-)
  • the IR-camera for the pi (25.-)
  • a wifi-stick for the pi (8.-)
  • a PIR-sensor (ebay 3.-)
  • a IR-LED floodlight (5.-)
  • a darlington-transistor and two resistors (e.g. BD649 and 10k and 2k)
  • a step-down-converter 12V to 5V (LM2596 DC-DC adjustable Step-Down ebay 3.-)

That's it.

Optional you can add some other sensors like a temperature-sensor or some noise-activated sensor or a light barrier.

And you can of course start without the PIR and the floodlight an later add it to the setup. If you only want some chatterbot, you don't even need the camera.

Step 2: Start With a Virtual Machine (optional)

Well this instructable has many different aspects: Hardware, software, python, lua, messenger. And I'm pretty sure at some point I forgot to mention some important step. So take this instructable not as a receipe but as a collections of hints what can be done and how. Then go out an figure it out by yourself.

So let's start with the software:

For 90% of the software development, I didn't use a real raspberry pi, but a virtual machine raspi. I tried to set up a virtual raspi some time ago, but then didn't know what to do with it. Because obviously you can't access the camera in a virtual raspi, nor the GPIOs or set up a virtual wifi hotspot. So what the heck?

Well for this instructable a virtual machine is really coming in handy! With a virtual pi, you can develop all the software with just your computer. No additional raspi, power, display, keyboard. No hustle with the wifi, connection, power-cords and so on. But of course you can do all the steps with a real raspberry pi too.

To start a virtual raspi you need:

  • Qemu
  • a raspberry Pi image
  • a windows-PC with some GB free space

I roughly followed this tutorial to set up the virtual raspi:

It is not really difficult and you find a lot of good tutorials. The main thing is that during the first boot, the name of the partitions have to be adjusted, because the raspi is not running on a sd-card but straight from the image-file.

This is the final line which starts my virtual raspi:

qemu-system-armw.exe -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda 2015-01-31-raspbian.img -redir tcp:5555: -redir tcp:80:

The -redir tcp-commands make sure the virtual raspi gets connected to the network.

Once the raspi starts, you can either log on in the QEMU window, like you would in an external raspi, or you could connect via ssh. Maybe you have to enable ssh with the "sudo raspi-config" command.

Step 3: Set Up the Real Pi

Well the real pi will surely have to be set up for the final thing, so If you want to skip the virtual machine, do it!

You need to install the image to the sd-card, boot the raspberry and connect it to your local network. This can either be done by ethernet or by wifi.

I prefer wifi, because it gives me the freedom to move the pi around in the house.

For the first setup of wifi you need to somehow connect to your pi. This can be done by adding a keyboard and a display to your pi, or connect it with a cable and use ssh, if enabled.

There are so many different tutorials about these steps, that I don't describe them in detail here.

Finally you should have a raspberry pi running and be able to connect to it with ssh from your computer.

If you plan to do more stuff with your raspberry pi, make a backup of the current system and start with this image instead of the default one. This way you don't have to adjust wifi every time! It's already there.

Step 4: Mobaxterm

Mobaxterm is one of the best xterminals for windows. It doesn't require installation and provides an X-server and a tabbed ssh-client on windows.

When using a virtual raspberry pi with qemu, you have to connect to the virtual machine using the "-p 5555" parameter. Even though the virtual machine tells you a completely different IP-address.

And my favorite feature of Mobaxterm really is the remote editing. You can right click any file on the remote connected system and open it with an editor on your pc. There are a lot good full-featured editors on pc with syntax highlighting and code-completing and many things more. OK, there might also be those features on the raspberry pi, but now over ssh. I personally prefer sublime text for editing, because it is really fast and provides a perfect gui. If you change something and press save, Mobaxterm asks you if you want to update the remote file too. If you select "autosave", the file is updated every time until you close the editor.

You can use your 4k-display, some kind of weired developer studio and update the files on the raspberry with a click and a smile. :-)

O.k., working with vi in a 640x480 pixel ssh-window might be also fast, but this really boosted my productivity!

Step 5: Update and Upgrade

Well the first thing after setting up a new raspberry pi is to change the default password for the user pi and to update the software.

The password can be reset with the command:


or via:

sudo raspi-config

After that you should update the software. I prefere to remove the wolfram-alpha engine from the original image before doing this, because it frees at least some 500MB and I don't need it. You can remove it with and then update it:

sudo apt-get remove wolfram-engine
sudo apt-get update

sudo apt-get upgrade 

Step 6: Add the Messenger

This is the key to the security-raspi: A console based messenger for linux: telegram.

Well this messenger is also discussed a bit controversial, because just like whatsapp it uploads all contacts on your phone and compare them to the database on the server. Then the messenger tells you which friends have the messenger too.

On the other hand: The messenger is completely free of charge (better than whatsapp) and it provides secured chats. And an installation on the raspberry pi will surely not steal any contact information! :-)

To get telegram running on the raspberry just follow this good instructables from emme shop: or

And I remember that I had to install some additional libaries to get the lua script working: sudo apt-get install lua-lgi libnotify-dev

But before you register the client, take the time to read the next step!

Step 7: Secret Trick to Register Telegram on Your Pi

If you finally want to communicate with your security-pi, then the telegram messenger needs it's own identity.

One way to achieve this is to use a landline phone to register the raspberry.

After entering

bin/telegram-cli -k

when asked about your phone-number, just type your landline phone number (with country-code and city-code) and press enter.

Then you are asked to enter the code or type call to get called. This is what we do now. Type in call and receive a phone call with a computer voice telling you the code. Write it down or enter it directly. Now the ID is registered to this phonenumber.

This is the only time you really need this phone-number.

The ID-information are now stored on your raspberry pi in the directory /home/pi/.telegram-cli

You can copy this whole directory and take the ID to another raspi or make a backup.

Step 8: Test the Messenger

If you are still connected with your raspi, then your messenger should be active by now.

If not start it again with the command:

bin/telegram-cli -k

Then use your phone with the telegram-app or install the desktop-version and send some messages to the raspberry.

Step 9: Script the Messenger

The lua script is the brain of the raspberry pi telegram installation.

The default-script has a lot of functions in it. I suggest that you fill in every function a command like:

print("Hello this is function (replace with name of the function)")

This way you can see which function is called when. Start the script-version with

bin/telegram-cli -k -s test.lua

and see what is happening.

The most important functions may be:

  • function on_msg_receive (msg)

  • function on_get_difference_end ()

  • function cron()

The first is obviously always called when a message is received. But not only this, it is also called when telegram displays a message that we sent! That's why there are the following lines in the function:

-- if this is a message from us to anyone else, skip interpreting
if( == our_id ) then return end

That means, if the message was sent from the raspi, then skip the rest of the function and return.

The second is called when the synchronisation ended. This is special for telegram, because the chat is backuped on the server and if you connect with another device, all chats are updated on this device.

The third is like the linux-cronjob and can be used to do things from time to time.

Step 10: Extended Ping - Pong

The script has the typical ping-pong-function already installed, that means if you send ping to the client running on the script, it will send you a pong back. You can do this for hours... :-)

If you want a reaction to different words you have to add some if-statements.

With some few words more this can get quite confusing. And you can not combine words or commands. The command has to be send as programmed. If you would send "Ping" instead of "ping" nothing would happen, because this is not the same word and the message text is compared with == to the string "ping".

Another possibility to find command-words in the message is to do this:

functionsnamen = { "help", "time" , "clock", "pid", "temp", "ping",
                    "start", "stop", "uptime" }
functionen = { sendhelp, sendtime, sendtime, sendpid, sendtemperature, sendping,
                startsecuritycam , stopsecuritycam, senduptime }

function checkforcommand( TOID, FROMID )
  for i, name in pairs(functionsnamen) do
    --print( i.." "
    if ( string.find(string.lower(commandstringarray[1]) , name ) ) then
      --print("Command: "" found.")
      functionen[i]( TOID, FROMID, commandstringarray )

-- in lua means comment. For the two lines above you can remove the comments and see what happens inside the function.

The checkforcommand is called from within the on_msg_receive with this:

if ( == our_id) then
    checkforcommand( msg.from.print_name , ) 

There are two arrays, one for the command to send called "functionsnamen" and the other one for the functions in the lua-script that are called in case one command is found.

With the string.lower() we convert the commandstringarray[1] to lower case and compare it to functionsnamen. This way it makes no difference if we write "Ping" or "pINg" or "PiNG" or anything like that.

You might have noticed that there is the commandstringarray. This has the following function: After receiveing a message, the complete text is parsed into this array. This way I can check if the first word of the message was "ping" and the second was something else and so on.The commandstringarray is an array of strings. Lua is quite easy with the variable-types and array-types.

To get the message into this array I wrote this function, which is obviously called before checkforcommand:

commandstringarray = {}

function messagetextinstringarray(msg)
  commandstringarray = {}
  leerzeichen = 1
  count = 1
  completestring = msg.text
  -- print( "checkfunction called: msg.text ist: "..completestring )
  leerzeichen = ( string.find(completestring, "%s" ) )
  while leerzeichen ~= nil do
      commandstringarray[count] = string.sub(completestring, 1, leerzeichen )
      -- print("a space found. Partstring: "..commandstringarray[count])
      completestring = string.sub(completestring, leerzeichen + 1 )
      count = count + 1  
      leerzeichen = ( string.find(completestring, "%s" ) )
  commandstringarray[count] = completestring

the loop is looking for a space " " separating two words and writes the partstrings to subsequent indexes of the array.

Step 11: Get the Raspberry to Do Something: Send the Uptime

Now we don't only want the lua-script to answer us. Sometimes we even want to get some information back from other parts of the raspi.

This is mainly done by bash-scripts.

If you want to know how long your raspberry pi is already running since the last reboot you can just enter


in the console and get some dates and loads back like:

10:40:47 up 3:33, 0 users, load average: 0,32, 0,13, 0,07

So if you want to send this information via telegram just call this function:

function senduptime( TOID )
  local handle = io.popen("uptime")
  local result = handle:read("*a")
  --print( result )
  send_msg ( TOID , result, ok_cb, false)

Step 12: Own Commands: Send Temperature

The same applies if you want to issue own commands like send the temperature.

When the command "temp" is received, the following function is called:

function sendtemperature( TOID )
 local handle = io.popen("/home/pi/telegram/")
  local result = handle:read("*a")
  -- print( result )
  send_msg ( TOID , result, ok_cb, false)

The shell-script itself contains this:

echo "scale=3; $(grep 't=' /sys/bus/w1/devices/w1_bus_master1/28-00044a4203ff/w1_slave | awk -F't=' '{print $2}')/1000" | bc -l

This line reads a DS18B20 digital temperature sensor and echos the result. Because we are reading the result and sending itself as a telegram message we finally receive the current temperature via telegram. Cool huh?

Step 13: Next Step: Running Telegram in a Screen

A screen? What is a screen now?

Well screen is a fine tool for linux, that gives our commands a destination.

Until now, we had started the telegram messenger while we were logged in, either direct or via ssh. And we were able to send messages with the command "msg Andy this is my message".

Now I would like that the linux cronjob is doing this for us. Starting telegram after boot and sending messages from time to time.

But how? The cronjob doesn't know where to type "msg Receipient Message" to.

This is where "screen" comes in handy! If we start the telegram client in a new screen session, we get a console with a name! And then we can tell cronjob: Send "msg Receipient Message" to the screen named telegramsession. And this works just like in a console, if cronjob would be logged in.

Ok, in the first place this seems quite confusing, but you just have to play around a bit and then its getting clearer.

Install screen with the following command:

sudo apt-get install screen

Start the telegram client in a new screen with the following script

# Start Telegram in a detached screen.
cd /home/pi/telegram/
screen -m -d -L -S TGScreenSession /home/pi/tg/bin/telegram-cli -k /home/pi/tg/ -s /home/pi/telegram/check.lua

In my setup the telegram-client is installed to /home/pi/tg , while the lua-script and all the bash-scripts are in /home/pi/telegram. I just wanted to separate these things a bit.

The command does the following: start a new detached (-d) screen with the name TGScreensession (-S) and execute the following command.

When you issue this command, nothing visible will happen. It's like always in Unix: No news are good news! But in the background the new screen is running.

You can see it if you type in

screen -ls

That lists all active screens with PID.TGScreenSession.

And if you want to see what's going on in there, type

screen -r (Your Number.TGScreensession)

and hit enter. This brings you to the screen, which itself is then "lost". That means once you (-r) REattach a screen, it becomes your active console and the screen-functions are lost. That means you can not go back to a screen from there. You then have to end telegram with "quit" or "safe_quit" and start a new screen.

Have a look at the screen-shot.

Step 14: Sending Anything With Telegram

Now we are ready to send anything from any application on the raspberry.

Let's take the time for instance. Say I want a message every 15 minutes with the current time. O.k. we could also do this with the cron()-function in the lua script, but this time we do it with a bash-script called

#!/bin/sh<br># Send message using Telegram message service
screen -S TGScreenSession -X eval "stuff 'msg Andy Its: `date +%H:%M` . Exactly!  '\\015"

This command sends everything inside the double-quotation marks to the screen named "TGScreenSession".

The stuff ' ...' \\015 are for the screen itself, the rest goes to the application running there, in our case: the telegram-client.

the `date +%H:%M` is replaced by the shell with the current time in the format Hour:Minute.

With the same principle you could also send a picture with the

# Send picture using Telegram message service
screen -S TGScreenSession -X eval "stuff 'send_photo $1 $2'\\015"

Here I made a trick, because a picture has a file-name and to hard-code it into the script would not be clever. So I used the shell-parameters $1 and $2.

The has to be called like this: Andy /home/pi/pictures/mynewpicture.jpg

This would send the "mynewpicture.jpg" to the user Andy, if there is a screen named TGScreenSession and the telegram-client is running in it.

Next step is about debugging!

Step 15: What If Nothing Happens?

When operating with screen and bash scripts sending something from here to there, sometimes it happens that nothing happens. And what now?

Here I listed some problems I accountered and how I solved them:

  1. make sure the screen is really running. If you have the screen reattached, then there might be no more screen. And all the automatic shell-scripts trying to send it to a screen fail. Normally they don't tell you about this.
    try "screen -ls" to see if there is a screen running.
  2. Also if you started telegram-cli directly from shell, then there is no screen.
    try "screen -ls" to see if there is a screen running.
  3. If there is a screen, try to reattach to see if telegram-cli is still running.
    with "screen -r (number.TGScreenSession)"
  4. A lot of times I changed something in the lua-script and tried to start the screen, it didn't work, because I made a typo in the script. So before trying to start the screen start with the telegram-cli and check that the lua-script is working
    try "bin/telegram-cli -k -W -s script.lua" if it works, enter "safe_quit" and start the screen.
  5. Some times I had the situation, that the telegram-cli didn't properly connect. You can see this in the picture. I don't know why, but if I sent a message to the raspberry, this state ended very quick.
  6. While playing around with several virtual and real raspis running on the same telegram ID, if often happened to me that after the start of telegram, while the chats were synchronised, the lua-script crashed because of the many messages. Use "function on_get_difference_end ()" to activate the message-handling by script. This function is called after the synchronisation is finished.
  7. If the lua script reacts on messages you send, you could easily end up in a deadlock. Like "time" would be the command and "Time is 12:34" is the answer. Then the command is found in the sent messages and the script would send endless messages.

Step 16: Adding Real Hardware: PIR

The next step is to add the PIR-sensor. I ordered a HC-SR501 from ebay in china. With below 3€ that was pretty cheap and it works perfect!

The power supply for this device ranges from 4.5V to 20V, while the detector-output always has 3.3V! Perfect for the raspberry pi!

To react on the output, I decided to write a python script, because I already have some experience on that. And it is very easy to combine the IOs with the camera and other stuff.

So what the python-script actually does is:

  • wait for the motion sensor to trigger
  • take a picture with the current date-time as filename
  • send the picture via telegram

Step 17: Add the IR Floodlight

The IR floodlight is the ultimate killer! Surveillance in absolute dark rooms with no noticable light for humans!

The IR floodlight is the really cheapest you can get in germany: IR floodlight and it's only 4.95€ plus shipping. But of course you can also find something similar on ebay or amazon.

It works with 12V and takes about 400mA when it is running. I say when, because the PIR-sensor doesn't need light to work. So I just wait for motion to be detected, then switch on the light (unvisible to human), take a picture and switch the light off again.

Of course the floodlight can not directy be connected to the raspberry pi. We need a 3.3V-safe switch for 12V and 400mA. The first thing to come in mind is a relay. But this is very noisy and the switching current caused voltage drops and instable operation on my raspberry pi. Because of this, I decided to use a darlington transistor.

I had a BD649 at hand and used this one. It can handle up to 8A of current, so it doesn't even warm up a bit at 400mA. :-)

You only need two resistors and the darlington-transistor to switch the floodlight safely.

Because I wanted to have a single power source only, I also installed a step-down converter from 12V to 5V. These devices cost less than 2€ at ebay. Just look for "LM2596 DC-DC adjustable Step-Down".

Step 18: Connect the Python Script and the Lua-script

Well after all that was running, I thought maybe it would be nice if I could somehow stop the python script and start it again via telegram. Just to make sure, the security-functions are initially off and could be activated by a simple "start"-command. That way you could check that the camera is pointed correctly and then leave the room and activate the photo-trap!

But how?

You would need to have a way that both scripts could talk with each other. And this can be done with sockets. A socket is like a mailbox. The script waits for someone to put something into the mailbox and if so reacts on it.

Those sockets can be implemented in python and lua and used to exchange any type of data.

Because I only wanted a one-way communication, I implemented a listener-thread in the python-script and the sender in the lua-script. If the lua script remembers what was it has sent to the python-script, we don't need to have a feedback.

These are the two website to look for help:

Step 19: Pack Everything in a Nice Housing

Or do it like I did and pack everything in a black cardboardbox.

In an earlier version I used a 7805 linear-converter to produce 5V for the raspberry, but it produced so much heat that after a few minutes I had more than 50°C in the box. With the step-down-converter it doesn't reach 40°C at all.

But most of the time I leave the box open anyway, because the LEDs on the raspberry are the only indication that it is running. And they are too dimm to be visible from the front.

Step 20: Why Is There No Software to Download?

When I started this project, I didn't have in mind that some day I would make an instructable on it.

Then it grew and grew and now it is a real mess. There is lua, python, the camera, the socket-communication from lua to phyton, telegram, several hardware issues and a lot of german names for variables and comments.

Therefore it's no use to just copy the lua-script to the raspi and start it. It won't run! You have to adjust all the paths, install the libraries to suit your setup.

If you start by yourself, you will encounter some of these problems and be able to solve them with the hints I provided. To write it down in a precise and complete matter would mean to do it all again and unfortunately I don't have the time for that.

My final software is just an extended combination from the code of step 9 to 15. But if you have detailed questions on some parts, feel free to ask. I will try to help you!

Step 21: Beside That: Who Would Like to Implement a Text-adventure-bot?

One of my favorite functions is the "rude-answer". In addition to the commands the lua-script is looking for "dirty" words in the message. Just a for-loop comparing one string-array to the message-string-array. And if a dirty word was found the scripts sends out another dirty word which is randomly picked from another string-array with answers. This is much more fun than the old ping-pong! :-)

Beside all the security features, you could also think of a lua-script that provides a classical text adventure. And if you include some kind of user-handling this could even be played by different players simultaniously.

Or an anonymus chat client, where your messages are relayed to some stranger? But who would use or need something like that?

Step 22: Addendum: Example for Socket Between Python and Lua-Scripts

In the two files on this step, there should be all information to set up the socket-communication.

The lua-side is so short because I only send data from lua to the python-script.

The other way round is performed by the messages to the screen.

I hope this helps when setting up the software.

Automation Contest

Participated in the
Automation Contest

Pi/e Day Contest

Participated in the
Pi/e Day Contest