低功耗+AI识别:基于树莓派的 LoRa 神经网络安防系统!

描述

 

这篇博客展示了如何使用树莓派上的神经网络USB插件来检测或“推断”一个人的位置,从而构建一个安全系统。Arduino型接收器从零开始构建,通过远程LoRa射频协议从树莓派发射器获取数据,并显示和发出警报。我试着展示了这个项目背后的一些想法,展示的是一整套python,arduino和PCB等等以便实施。

 

难度级别:需要具备一定的树莓派技能但是并非专家级,焊接技能简单。

网络上关于LoRa的大部分信息似乎都指向“Things Network”,但如果我们只需要在两个设备之间进行基本数据传输,而不希望全世界都能看到我们的数据,该怎么办呢?那就需要点对点通信了。

在本例中,树莓派搭配Dragonino LoRa/GPS扩展板,将远程位置(如农场大门)的安全状态数据发送出去,以告知我们是否有人进入,甚至是否有人偷走了我们的牛。接收器是Arduino MKRWAN 1300,上面焊接了专用的LoRa芯片。注意:这款Arduino是3.3V设备,如果向任何(或大多数)引脚施加5V电压,设备将被烧毁。此外,在未连接天线的情况下,切勿操作Dragino扩展板或Arduino设备!就代码而言,两者都非常简单,尽管我花了一段时间才弄清楚需要为Arduino刷入固件升级才能使其正常工作。插入Dragino扩展板后,树莓派的处理步骤如下:

  •  
  •  
  •  
  •  
  •  

$ wget "https://codeload.github.com/dragino/rpi-lora-tranceiver/zip/master> "https://codeload.github.com/dragino/rpi-lora-tran...> "https://codeload.github.com/dragino/rpi-lora-tran...> "https://codeload.github.com/dragino/rpi-lora-tran...> "https://codeload.github.com/dragino/rpi-lora-tran...> https://codeload.github.com/dragino/rpi-lora-tran...>>>>>$ unzip master$ cd rpi-lora-tranceiver-master/dragino_lora_app$ make$ cd rpi-lora-tranceiver-master/dragino_lora_app &&./dragino_lora_app$ ./dragino_lora_app sender

 

此数据不安全,但如有需要,可以使用Python脚本。

重要提示:RPi必须配备合适的电源,并在设置中启用SPI。使用的操作系统是Raspian Stretch。Arduino的设置同样简单,但需注意以下几点:

首先,在我的案例中,RPi尝试每3秒在868.1 MHz频率上发送“HELLO”,因此Arduino需相应配置……868.1 MHz = 8681 x 105 = 8681E5。其他地区(如美国)使用不同频率。然后在从此处下载Arduino LoRa库(两者均需安装)

 

以正常方式安装库后,打开MKWAN示例集,将“MKRWANFWUpdate _ standalone”加载到Arduino并打开串行控制台。观察更新进度,接下来,找到“LoRa”示例集,选择“LoRaReceiver”并上传。不要忘记像前面提到的那样编辑频率!打开串行控制台,您应该会看到从RPI发送的HELLO。

神经网络

第一步:组件清单

神经网络神经网络

Arduino MKRWAN 1300

树莓派3

RS PRO 5V表面贴装电磁蜂鸣器,97dB(3个)

PCB滑动开关(单刀双掷,锁存型,3A @ 120V AC)

L293E电机驱动IC(STMicroelectronics,36V 1A)

Draganino Seeed Studio Raspberry Pi LoRa/GPS HAT(支持868MHz)

Arduino PCB天线

树莓派PiNoir相机V2模块(CSI-2,3280×2464分辨率)

Logitech C930e全高清摄像头

Movidius神经网络计算棒NCSM2450.DK1

USB延长线(12CM USB 2.0 AM AF BLK EXT)

带透明盖的机箱

39Ω电阻

第二步:将代码移植到Python

 

由于神经网络模块使用Python 3,我认为让树莓派的LoRa发射器HAT(Dragonino)也通过Python控制更合理。

但需补充几个步骤,此处详细说明:

1.从RPi取出SD卡,插入合适的PC。

2.将/boot文件夹中的config.txt复制到桌面。

3.使用chmod 777修改权限,编辑文件并添加:

  •  

dtoverlay=spi0-cs,cs0_pin=25 

到文件顶部。

4.保存后将文件复制回SD卡的boot文件夹。这是唯一快捷的编辑方式!

5.下载Python文件: https://github.com/mayeranalytics/pySX127x , 解压后用文本编辑器打开 'board_config.py'。

6.在board_config中设置以下值:

  •  
  •  
  •  
  •  
  •  
  •  

DIO0 = 4     DIO1 = 23     DIO2 = 24     DIO3 = 21     LED = 18     SWITCH = 7

注意:若在欧洲,使用868 MHz频段,需将low_band = true改为false(根据注释说明)。

  •  

low_band = true

7.修改constants.py文件,添加以下内容(注意用4个空格缩进以兼容Python格式):

  •  
  •  
  •  
  •  
  •  
  •  

@add_lookup class SPI_BAUD_RATE:     MAX_SPEED_HZ = 5000 @add_lookup class SPI_MODE:    SPI_MODE = 0b01 

8.打开LoRa.py文件,找到spi = BOARD.SpiDev():

  •  

spi = BOARD.SpiDev()

在其下插入

  •  
  •  

spi.max_speed_hz = SPI_BAUD_RATE.MAX_SPEED_HZ spi.mode = SPI_MODE.SPI_MODE 

9.打开终端,进入包含tx_beacon.py的目录(如cd /home/pi/Desktop/dragonino/psySX127x-master/)。

10.其中,“869”是以MHz为单位的频率,“7”是扩频因子,使用python tx_beacon.py -f 869 -s 7运行信标程序

11.将Arduino调至8690E5,串口控制台应显示类似以下内容:

  •  
  •  
  •  
  •  
  •  

Received packet ' ' with RSSI -33Received packet ' ' with RSSI -23Received packet ' ' with RSSI -33Received packet ' ' with RSSI -26Received packet ' ' with RSSI -25

成功!

12.如需显示更有意义的内容,用文本编辑器打开tx_beacon.py,找到第65行附近的:

  •  

self.write_payload([0x0f])

修改为:

  •  

self.write_payload([0x57,0x68,0x61,0x74,0x20,0x74,0x68,0x65,0x20,0x66,0x75,0x63,0x6B,0x21]) 

 

第三步:准备Python传输数据

我以前没有用Python编程过,但是与C++相比,它已经看起来简单多了,也直观多了。

我发现Lora信标可能是起点,它需要一个代表ANSII字符的数字“列表”,这些数字可以是十进制或十六进制值。信标程序中传输数据的实际短语在第65行:

  •  

self.write_payload(j)

其中j是有效载荷列表,对于“Hello World”来说,它通常看起来像这样:

  •  

([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100])

为了将“Hello World”转换成该列表格式,使用了以下代码:

  •  

import array as arr
import numpy as np

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

c= 'Hello World'g = arr.array('i',[])n=-1for h in range(len(c)):  g.extend([0]) for x in c:  n = n+1  y = ord(x)  g[n] = yprint(g)j = np.array(g).tolist()

代码将字符串中的每个字符转换为整数数组中的一个整数,用字母“I”表示,长度为c,对应于字符串中字符和空格的数量。extend命令扩展数组以接受更多的整数。接下来,对于字符串中的每个字符,“ord”命令执行实际的字符到整数的转换,然后“g[n] = y”将其转储到数组中的正确位置。最后一个是array to list命令,它将整个数组转换成列表格式。简单!

在本博客的文件部分,新的LoRa信标文件被称为Tegwyns_LoRa_Beacon,假设它与原始信标文件位于同一位置,它将从命令行运行:

  •  

cd /home/pi/Desktop/dragonino_python_fix/pySX127x-master/ && python3 Tegwyns_LoRa_Beacon.py -f 869 -s 7-

在这一阶段,使用SDR-RTL USB加密狗通过Cubic SDR等软件及其频谱分析仪功能来检测和分析传输信号是一个好主意,但不是必需的。

神经网络

y

第四步:使用神经计算棒实现“人物检测”

神经网络

开始之前需要注意几个关键事项:

树莓派的正确神经计算棒是NCSM2450。DK1,目前(2018年)没有其他英特尔棒将在树莓派上工作。注意下载的是stick SDK还是APi的哪个版本——V2及以上版本不是针对Raspbian stretch的,仅支持Ubuntu 16.04。

说明:

1.安装SDK 1.0完整版和API(耗时较短):

  •  
  •  
  •  
  •  
  •  

$ sudo apt-get update$ sudo apt-get install$ git clone https://github.com/movidius/ncsdk.git$ cd /home/pi/ncsdk && sudo make install$ cd /home/pi/ncsdk && sudo make examples

2.测试计算棒是否正常工作:

  •  
  •  
  •  

$ git clone https://github.com/movidius/ncappzoo$ cd /home/pi/ncappzoo/apps/hello_ncs_py$ python3 hello_ncs.py 

3.下载文件: https://cdn.hackaday.io/files/1626676959544928/graph 并粘贴到 /home/pi/ncappzoo/caffe/SSD_MobileNet文件夹.不要改变名字和扩展名.

4. 编译并运行演示:

  •  
  •  

$ cd /home/pi/ncappzoo/apps/security-cam$ make run

需使用摄像头(如USB Logitech,即插即用)。

 

第五步:整合LoRa与安全摄像头

神经网络

这有点像一场战斗,Python的学习曲线很陡,但是最后,我创建了一个Python文件,可以将时间戳、检测类别、置信度和边界框坐标发送到Arduino基站。显然,在不同的目录中仍然有大量的依赖关系——一些就在附近,而另一些则深深地嵌入在Python系统的某个地方,此处是我的“栈顶”代码:

 

第六步:升级摄像头至树莓派NoIR V2

神经网络

显然,我们想在黑暗中用红外线灯使用这个小工具,所以我们需要一个有红外线功能的像样的相机,既没有红外线过滤器的相机。幸运的是,这些相机比罗技USB便宜得多,也更紧凑,而且安装也很容易:

首先,检查树莓派设置中的摄像头是否已启用,然后,在将其插入主板后,检查它是否能与以下设备一起工作:

  •  

$ raspistill -o image.jpg

接下来安装以下 Python 依赖项

  •  
  •  
  •  

$ sudo apt-get install python3-picamera$ pip3 install "picamera[array]"$ pip3 install imutils

最后,使用树莓派cam版本的security_cam文件

用以下命令运行文件

  •  

$ cd && cd /home/pi/ncappzoo/apps/securityCam && python3 security_camPiCam.py

安全摄像头现在可以在野外测试了,显然不是在雨中!如果有一个像样的天线,可以看看发射机的范围会很有趣:)

需要注意的一点是,Noire相机给出的色彩平衡结果与USB相机非常不同,这是完全正常的,因为镜头上没有红外滤光片。

除了防水之外,另一个问题是当设备发现一个人时,在哪里收集拍摄的照片-也许是一个u盘,以防止填满树莓派SD卡?

第七步:将摄像头快照保存到USB驱动器

神经网络

通过将第235行修改为类似下面的内容,可以很容易地修改安全cam Python文件,以保存检测到的人的重复快照,其中我的USB驱动器称为“KINSTON”:

  •  

photo = ( "/media/pi/KINGSTON" + "/captures/photo_" + cur_time + ".jpg" )

实际上,使用这个u盘大大降低了程序的运行速度!部署后,如果使用另一台PC通过SSH连接到树莓派,则可以轻松地从树莓派传输/删除图像。一个更好的解决方案可能是在micro SD卡上创建一个分区,这样如果它充满了图像,它就不会阻塞操作系统和相机python脚本。

第八步:接收器PCB组装

神经网络

神经网络

神经网络

除了Arduino MKRWAN 1300之外,PCB还具有一个L293E芯片,用于提高报警系统所需的电压和电流,该系统本身是一个由8个led和3个蜂鸣器芯片组成的模块。如果直接在Arduino上运行这些设备会立刻让设备崩溃!在组装和测试后,整个系统运行良好,经过实验,红色发光二极管的最佳电阻是39欧姆。

虽然大多数元件都是表面贴装,但它们都非常大,不需要模板。检查完led的极性后,用焊料将PCB粘好,安装表面贴装元件,然后夹在烤箱中加热至260摄氏度。可以使用热风枪,但不建议使用。

 

第九步:部署摄像头

神经网络

神经网络

可以看出,这种装置非常容易组装,只需要放在一个前面透明的防水盒中。使用厚纸板和一点折纸将上述组件紧紧地楔入盒子中。

注意:摄像头必须在正确的方向上,神经网络才能正常工作。

第十步:Arduino MKRWAN 1300代码

神经网络

代码没什么特别的,除了可以让蜂鸣器的音调根据被检测的人离摄像机的距离而改变。这将有助于辨别在邮箱里寄信的人和真正走上车道的人之间的区别。该代码使用字符串分析函数,首先通过搜索单词“Box”来确认数据是一致的,然后找到代表检测框的两对坐标。如果检测到的人靠近摄像机,检测框的面积会更大,产生的报警音频率会更高:

  •  
  •  

#include #include String myString =" ";String myStringReversed =" ";void setup() {  pinMode(4, OUTPUT);  pinMode(LED_BUILTIN, OUTPUT);  tone(5,1000,1000);  digitalWrite(LED_BUILTIN, HIGH);  digitalWrite(4, HIGH);  delay(1000);  digitalWrite(LED_BUILTIN, LOW);  digitalWrite(4, LOW);  Serial.begin(9600);

//  while (!Serial);  Serial.println("LoRa Receiver");  if (!LoRa.begin(8690E5)) {    Serial.println("Starting LoRa failed!");    while (1);  }}void loop() {  //delay (1000);  

// try to parse packet  int packetSize = LoRa.parsePacket();  if (packetSize)  

 {    // received a packet    Serial.print("Received packet '");  digitalWrite(LED_BUILTIN, HIGH);  digitalWrite(4, HIGH);  delay(100);  digitalWrite(LED_BUILTIN, LOW);  digitalWrite(4, LOW);    // read packet    myString =" ";    myStringReversed =" ";    int i = 0;    char c;    while (LoRa.available())     

{      //c[i] = (char)LoRa.read();      //Serial.print((char)LoRa.read());      myString = (char)LoRa.read() + myString;      i++;      //Reverse the string:      c = myString.charAt(0);      myStringReversed = myStringReversed + c;    }    processString();    //Serial.print("My string:

 ");Serial.print(myString);    // print RSSI of packet    //Serial.print("' with RSSI ");    //Serial.println(LoRa.packetRssi()); 

 }}void processString(){    Serial.print("My string reversed:");Serial.print(myStringReversed);    // print RSSI of packet    Serial.print("' with RSSI ");    Serial.println(LoRa.packetRssi());  

  int len = myStringReversed.length();    int j=0;    char a,b,c,d;    String coord1 = " ";    String coord2 = " ";    String coord3 = " ";    String coord4 = " ";  

  int k =0;    char x = ',';  

  int z=1;    int y=1;    int r=1;    int s=1;    int v=0;    while (j < len)    

 {      a = myStringReversed.charAt(j);      b = myStringReversed.charAt(j+1);   

   c = myStringReversed.charAt(j+2);   

   if((a=='B')&&(b=='o')&&(c=='x'))                           // The word 'box' has been identified in the string - k is now greater than 0.      {        k = j+5;        Serial.print("Character B was found at: ");Serial.println(j);      }      j++;    }    if (k>0)    {      v =0;                    

                                  // int V stops perpetual loops occurring.      while((z==1)&&(v<200))      {        if(myStringReversed.charAt(k)==x)     

                   // Build up string 'coord' until a comma is reached.        {          Serial.print("k");Serial.println(k);    

      z=0;        }   

     else     

   {        coord1 = coord1 + myStringReversed.charAt(k);        k++;        v++;        //Serial.print("coord1: ");Serial.println(coord1);         }      }       v =0;       k++;      while((y==1)&&(v<200)) 

     {        if(myStringReversed.charAt(k)==')')       

 

                 // Build up string 'coord' until a comma is reached.        {          Serial.print("k");Serial.println(k);          y=0;        }        else        {      

  coord2 = coord2 + myStringReversed.charAt(k);        k++;        v++;        //Serial.print("coord2: ");Serial.println(coord2);         }      }        v =0;      k=k+3;        

                           

                  // Takes account of two brackets and a comma.      while((r==1)&&(v<200))      {        if(myStringReversed.charAt(k)==x)        

                // Build up string 'coord' until a comma is reached.     

   {          Serial.print("k");Serial.println(k);          r=0;        }        else        {   

     coord3 = coord3 + myStringReversed.charAt(k);     

   k++;        v++;        //Serial.print("coord3: ");Serial.println(coord3);         }      }        v =0;      k++;      while((s==1)&&(v<200))      {     

   if(myStringReversed.charAt(k)==')')                        // Build up string 'coord' until a comma is reached.        {    

      Serial.print("k");Serial.println(k);          s=0;      

  }        else      

  {        coord4 = coord4 + myStringReversed.charAt(k);        k++;        v++;        //Serial.print("coord4: ");Serial.println(coord4);       

  }      }      }    Serial.print("coord1: ");Serial.println(coord1);    Serial.print("coord2: ");Serial.println(coord2);    Serial.print("coord3: ");Serial.println(coord3);    Serial.print("coord4: ");Serial.println(coord4);    int coord10 = coord1.toInt();    int coord20 = coord2.toInt();    int coord30 = coord3.toInt();    int coord40 = coord4.toInt();    int area = (coord40 - coord20) * (coord30 - coord10);    tone(5,(area/100)+200,100);    Serial.print("Box area: ");Serial.println(area);}

 

第十一步:检测其他对象和动物

神经网络

“security_cam.py”文件是一个通用的“活体检测”文件脚本,可以很容易地修改,以检测总共20个不同的对象。

如果我们看第119行:

  •  
  •  

# "Class of interest" - Display detections only if they match this class IDCLASS_PERSON         = 15

要检测狗,只需将其更改为:

  •  
  •  

# "Class of interest" - Display detections only if they match this class IDCLASS_DOG         = 12

此外,第200行也需要更改: 

  •  
  •  

        # Filter a specific class/category        if( output_dict.get( 'detection_classes_' + str(i) ) == CLASS_PERSON ):

虽然person类工作得非常好,给人留下了深刻的印象,但是dog类就有点令人印象不深,远不如我测试过的其他一些模型。尽管如此,这是这种模型可用的全部类列表:飞机 自行车 鸟 船 瓶子 公共汽车 猫 椅子 牛 餐桌 狗 马 摩托车人 盆栽 植物 羊 沙发 火车 电视监视器

第十二步:系统测试


神经网络

在将系统置于headless模式并使用SSH通过笔记本电脑登录后,我能够在“现场”测试系统。最初,有一个错误导致相机在15分钟后关闭,这是通过在树莓派上安装“screen”并在启动python文件之前在命令行中键入“screen”来解决的。screen所做的是打开树莓派上的另一个终端,因此它有自己的活动终端,当我的笔记本电脑终端关闭时,它不会关闭。这是一个非常好的解决方案,避免了与其他“启动时运行”解决方案的混乱,而且后者可能会破坏整个系统。

一台独立的摄像机安装在我的办公室里,在200米外,与主摄像机同步,聚焦在接收器上(视频右下角)。在测试中,系统对相机画面中的狗没有反应,但对我(一个人)有反应…..成功!

我打算在某个阶段将整个系统升级到Movidius neural stick 2,并使用一个更大的带分区的micro SD卡,来防止拍摄的图像堵塞。

 

原文地址:
 

https://www.instructables.com/LoRa-Neural-Network-Security-System/

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分