精华内容
参与话题
问答
  • 树莓派小车专栏的附属文件,主要内容是代码,包括安卓客户端的代码,小车的代码(语言为python),还附带了一个生成好的apk文件,可以尝试直接安装,不适用的话可以重新生成一个适用自己手机的版本。
  • 树莓派UDP通信及串口通信

    万次阅读 2014-05-23 14:01:12
    树莓派UDP通信及串口通信

                             树莓派UDP通信及串口通信

              
           该程序运行在树莓派上,主要功能是把收到的UDP消息通过树莓派自带串口发给下位机,同时把串口收到的数据通过UDP发送出去,使用threading模块启动两个线程,互不干涉,可以在此基础上更改实现各种功能。
           我写这个是用于四轴飞行器控制的,树莓派和stm32搭在飞行器上,地面用手机控制,可以实现飞行器姿态及参数实时监测控制,同时树莓派接摄像头,传航拍图像给地面手机。下面的程序只是通信部分的,关于摄像头视频流的捕获及上传程序和手机端的程序工程较大,等忙过这一段时间会上传的。

               首先,树莓派在使用串口之前是需要配置一些文件的。

             1.修改
    cmdline.txt
                     >>> sudo vi /boot/cmdline.txt

                     将原来的内容

    dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

     修改成

    dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

    •           2. 修改
      inittab
          >>> sudo vi /etc/inittab
          将下面这一行加#注释掉,一般是最后一行
         #T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
    
    
        3.安装python-serial
         >>>sudo apt-get install python-serial
    
    
        现在就可以用了,下面贴上源代码:
        
    #!/bin/env/python
    import serial
    import string
    import time
    import threading
    import socket
    host=''
    port=10001
    global addr  #UDP 客户端的IP地址,必须设为全局变量,才能在线程间共享
    s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
    s.bind((host,port))
    ser = serial.Serial('/dev/ttyAMA0',9600,timeout =0.1) #串口设置
    if ser.isOpen() == False:
            ser.open()
    class timer(threading.Thread): # timer class 
            def __init__(self, num, interval):
                    threading.Thread.__init__(self)
                    self.thread_num = num
                    self.interval = interval
                    self.thread_stop = False
    
            def run(self):
                    global addr
                    while 1:
                            if self.thread_num == 1:
                                    try:
                                            data,addr=s.recvfrom(1024) #接收到的UDP消息
                                            print"got data from",addr
                                            ser.write(data)  #将UDP内容通过串口发送至下位机
                                    except  KeyboardInterrupt:
                                            raise
                            if self.thread_num == 2:
                                    try:
                                            re = ser.readlines() #收到的串口数据
                                            print re
                                            c=''.join(re)  
                #sendto()第一个参数是str,而readlins()返回值类型是list,故需要先将list转换为str再发送,之前              数据不断丢包,一直不明白是这个原因。
                                            s.sendto(c,addr)  #将串口数据通过UDP发送出去
                                    except:
                                            pass
    
                          # time.sleep(self.interval) 
    def test():
            thread1 = timer(1, 0.1) #UDP recev and serial send
            thread2 = timer(2, 0.1) #serial recev and UDP send
            thread1.start()
            thread2.start()
            return
    
    if __name__ == '__main__':
            test()

           直接在终端里输入python 文件名.py 即可运 行
           附上源程序下载链接 点击打开链接

    展开全文
  • 主要介绍了Python树莓派学习笔记之UDP传输视频帧操作,结合实例形式详细分析了Python树莓派编程中使用UDP协议进行视频帧传输的相关操作技巧与注意事项,需要的朋友可以参考下
  • 树莓派笔记8:UDP传输视频帧

    千次阅读 2018-02-19 19:53:19
    因为我在自己笔记本电脑上没能成功安装OpenCV-Contrib模块,因此不能使用人脸识别等高级功能,不过已经在树莓派上安装成功了,所以我想实现把树莓派上采集的视频帧传输到PC的功能,这样可以省去给树莓派配显示屏的...

    因为我在自己笔记本电脑上没能成功安装OpenCV-Contrib模块,因此不能使用人脸识别等高级功能,不过已经在树莓派上安装成功了,所以我想实现把树莓派上采集的视频帧传输到PC的功能,这样可以省去给树莓派配显示屏的麻烦,而且以后可能可以用在远程监控上。

    1 UDP还是TCP

    首先考虑用哪种传输方式,平常TCP用的非常多,但是像视频帧这种数据用TCP不是太合适,因为视频数据的传输最先要考虑的是速度而不是准确性,视频帧的数据量很大,帧间隔也非常短,需要尽量保证传输速度,同时丢失一些数据是无所谓的。TCP需要维护连接、保证数据包正确,会耗费一些时间,因此应该使用UDP,就像所有参考书上说的,UDP不在乎是否建立连接,也不管数据是否能被准确接收,只关心能否把数据发送出去而已。

    在Python的socket代码中也可直观地看到UDP的特点,对于发送方,我们通过server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)创建UDP套接字对象,然后执行server.connect((HOST,PORT)) 指定发送方地址,但其实connect函数直接就返回了,不像TCP中的客户端会等待连接成功,接着就可直接在套接字对象上调用send函数发送数据了,这个过程根本没确立连接。

    2 图像传输中的编解码

    但是用UDP传输图像有一个很关键的问题需要考虑,就是图像的大小。根据UDP协议,单个包的数据大小最大只能65507个字节(去掉包头),而一般直接从摄像头采集的图像帧的大小比这个数要大得多,以我的逻辑C270为例,单幅图像的大小为480X640X3个字节,远大于65507,因此一个包是没法发送完的。解决方法有两种,一种是把图像拆成几次进行发送,相应的接收端用个循环多次接收,这种方法可以完整地接收数据,但是速度肯定受到影响,而且可能要添加一些自定义规则,徒增麻烦;另一种方法就是发送前先对图像进行编码压缩,接收后再解码,清晰度会有所下降,但是可以保持速度上的优势,这种方式比较合适。

    OpenCV中的imencode和imdecode方法可分别用于图像的编码和解码。imencode根据指定的标识将图像数据编码并存入缓存区,函数原型为cv2.imencode(ext, img[, params]) → retval, buf,ext为文件扩展名,指定了存储格式,如’.jpg’;img为需要编码的图像数据; params为指定的编码标识,其形式为paramId_1, paramValue_1, paramId_2, paramValue_2, ... ,对于jpg格式,可以指定标识为CV_IMWRITE_JPEG_QUALITY ,其对应的值在0到100之间,表示了压缩质量,值越大压缩率越大,编码后的数据量越小,但解码后的图像质量也越差。
    imdecode从缓存区读取图像数据,通过指定标识,可以实现指定的解码格式。imdecode的函数原型为cv2.imdecode(buf, flags) → retval ,其中flags指定图像的读取类型,实际上就是指定了以多少深度多少通道读取图像,比如CV_LOAD_IMAGE_ANYDEPTH(即整数2)表示单个通道,深度不变的灰度图;CV_LOAD_IMAGE_COLOR(即整数1)表示3通道、8位深度的彩色图。

    3 树莓派程序

    结合套接字对象和编解码函数,就可以编写发送端的代码了,不过还有一个需要注意的地方是发送和接收的数据格式问题,套接字的发送和接收都是字节流,或者说是byte数组,发送数据时需要以字节流格式发送,接收数据后需要把字节流类型转换成合适的数据类型。
    从摄像头获取的图像是480X640X3的numpy.ndarray类型,通过imencode编码,得到?X1的numpy.ndarray对象,经测试,这个对象可以直接发送出去;在接收端,获得的是byte数组,这个数组直接做imdecode的参数会报错,经调试,发现还需要把数组转换成numpy.ndarray类型。树莓派作为发送端,其Python代码如下:

    import cv2
    import numpy
    import socket
    import struct
    
    HOST='192.168.1.122'
    PORT=9999
    
    server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #socket对象
    server.connect((HOST,PORT))
    print('now starting to send frames...')
    capture=cv2.VideoCapture(0) #VideoCapture对象,可获取摄像头设备的数据
    try:
        while True:
            success,frame=capture.read()
            while not success and frame is None:
                success,frame=capture.read()  #获取视频帧
        result,imgencode=cv2.imencode('.jpg',frame,[cv2.IMWRITE_JPEG_QUALITY,50])  #编码
        server.sendall(struct.pack('i',imgencode.shape[0])) #发送编码后的字节长度,这个值不是固定的
        server.sendall(imgencode) #发送视频帧数据
        print('have sent one frame')
    except Exception as e:
        print(e)
        server.sendall(struct.pack('c',1)) #发送关闭消息
        capture.release()
        server.close()

    在代码中,首先把编码后的字节长度发送了过去,目的是让接收端可以进行简单的校验,并且接收端可以据此判断是否应该关闭程序,相应的,自定义单字节的1为关闭消息。

    4 PC端程序

    自己的电脑作为接收端,为了解码数据,需要把原始字节流转成numpy.ndarray对象,代码如下:

    import cv2
    import numpy
    import socket
    import struct
    
    HOST='192.168.191.122'
    PORT=9999
    buffSize=65535
    
    server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #创建socket对象
    server.bind((HOST,PORT))
    print('now waiting for frames...')
    while True:
        data,address=server.recvfrom(buffSize) #先接收的是字节长度
        if len(data)==1 and data[0]==1: #如果收到关闭消息则停止程序
            server.close()
            cv2.destroyAllWindows()
            exit()
        if len(data)!=4: #进行简单的校验,长度值是int类型,占四个字节
            length=0
        else:
            length=struct.unpack('i',data)[0] #长度值
        data,address=server.recvfrom(buffSize) #接收编码图像数据
        if length!=len(data): #进行简单的校验
            continue
        data=numpy.array(bytearray(data)) #格式转换
        imgdecode=cv2.imdecode(data,1) #解码
        print('have received one frame')
        cv2.imshow('frames',imgdecode) #窗口显示
        if cv2.waitKey(1)==27: #按下“ESC”退出
            break
    server.close()
    cv2.destroyAllWindows()

    5 测试

    因为我树莓派上的OpenCV只关联了Python2,因此以python2 UDP_Frame_Send.py 的命令启动发送程序(接好摄像头);电脑上,在开始菜单中输入cmd进入Windows的控制台,进入程序文件目录,输入python UDP_Frame_Recv.py启动接收程序,结果表明可以比较流畅地窗口显示,不过有几个问题,一是在树莓派上,程序有时候打不开摄像头,需要重启几次程序,二是在电脑上,recvfrom这个函数是阻塞式的,在Windows系统的控制台中似乎没办法用键盘中断强制从这个函数退出,所以如果发送端出错接收端的程序就没法正常退出了,对此可以用TCP&UDP调试助手手动发送单个字节的1来终止程序。

    展开全文
  • 今天解决了一个困扰好几天的问题,由于比赛需要,需要用java语言,并采用UDP传输协议,让树莓派与服务器(就是本机)建立连接传输视频,图片。 由于UDP是建立在无连接的协议上,因此就碰到了一个很尴尬的问题,就是...

    今天解决了一个困扰好几天的问题,由于比赛需要,需要用java语言,并采用UDP传输协议,让树莓派与服务器(就是本机)建立连接传输视频,图片。

    由于UDP是建立在无连接的协议上,因此就碰到了一个很尴尬的问题,就是客户端一直发送,但是在本地服务器就是接收不到数据,最恶心的是根本不报错,所以根本不知道错在了哪。在讲过查阅资料后,终于解决了该问题,

    1.首先,要先将树莓派和本地服务器的防火墙都关掉。

    2.其次就是代码中的一些参数需要注意,具体代码如下:

    复制代码
    package UDPTest;
    
    import java.net.DatagramPacket;  
    import java.net.DatagramSocket;  
    import java.net.InetAddress;  
     
    public class Client {  
       public static void main(String[] args) {  
           try {  
               // 创建发送方的套接字,IP默认为本地,端口号随机  
               DatagramSocket sendSocket = new DatagramSocket();  
     
               // 确定要发送的消息:  
               String mes = "你好!接收方!";  
     
               // 由于数据报的数据是以字符数组传的形式存储的,所以传转数据  
               byte[] buf = mes.getBytes();  
     
               // 确定发送方的IP地址及端口号,地址为本地机器地址  
               int port = 12306;  
    //这里填写的服务器的IP地址 InetAddress ip = InetAddress.getByName("192.168.43.57"); // 创建发送类型的数据报: DatagramPacket sendPacket = new DatagramPacket(buf, buf.length,ip, port); // 通过套接字发送数据: sendSocket.send(sendPacket); // 确定接受反馈数据的缓冲存储器,即存储数据的字节数组 byte[] getBuf = new byte[1024]; // 创建接受类型的数据报 DatagramPacket getPacket = new DatagramPacket(getBuf, getBuf.length); // 通过套接字接受数据 sendSocket.receive(getPacket); // 解析反馈的消息,并打印 String backMes = new String(getBuf, 0, getPacket.getLength()); System.out.println("接受方返回的消息:" + backMes); // 关闭套接字 sendSocket.close(); } catch (Exception e) { e.printStackTrace(); } } }
    复制代码

    接收端代码如下:

    复制代码
    package UDPTest;
    
    import java.net.DatagramPacket;  
    import java.net.DatagramSocket;  
    import java.net.InetAddress;  
    import java.net.SocketAddress;  
     
    public class Server {  
       public static void main(String[] args) {  
           try {  
               // 确定接受方的IP和端口号,IP地址为本地机器地址  
               InetAddress ip = InetAddress.getLocalHost();  
               int port = 12306;  
     
               // 创建接收方的套接字,并制定端口号和IP地址  
               DatagramSocket getSocket = new DatagramSocket(port, ip);  
     
               // 确定数据报接受的数据的数组大小  
               byte[] buf = new byte[1024];  
     
               // 创建接受类型的数据报,数据将存储在buf中  
               DatagramPacket getPacket = new DatagramPacket(buf, buf.length);  
     
               // 通过套接字接收数据  
               getSocket.receive(getPacket);  
     
               // 解析发送方传递的消息,并打印  
               String getMes = new String(buf, 0, getPacket.getLength());  
               System.out.println("对方发送的消息:" + getMes);  
     
               // 通过数据报得到发送方的IP和端口号,并打印  
               InetAddress sendIP = getPacket.getAddress();  
               int sendPort = getPacket.getPort();  
               System.out.println("对方的IP地址是:" + sendIP.getHostAddress());  
               System.out.println("对方的端口号是:" + sendPort);  
     
               // 通过数据报得到发送方的套接字地址  
               SocketAddress sendAddress = getPacket.getSocketAddress();  
     
               // 确定要反馈发送方的消息内容,并转换为字节数组  
               String feedback = "接收方说:我收到了!";  
               byte[] backBuf = feedback.getBytes();  
     
               // 创建发送类型的数据报  
               DatagramPacket sendPacket = new DatagramPacket(backBuf,  
                       backBuf.length, sendAddress);  
     
               // 通过套接字发送数据  
               getSocket.send(sendPacket);  
     
               // 关闭套接字  
               getSocket.close();  
           } catch (Exception e) {  
               e.printStackTrace();  
           }  
       }  
    }  

    转载于:https://www.cnblogs.com/shyshy/p/11028660.html

    展开全文
  • 今天解决了一个困扰好几天的问题,由于比赛需要,需要用java语言,并采用UDP传输协议,让树莓派与服务器(就是本机)建立连接传输视频,图片。 由于UDP是建立在无连接的协议上,因此就碰到了一个很尴尬的问题,就是...

    今天解决了一个困扰好几天的问题,由于比赛需要,需要用java语言,并采用UDP传输协议,让树莓派与服务器(就是本机)建立连接传输视频,图片。

    由于UDP是建立在无连接的协议上,因此就碰到了一个很尴尬的问题,就是客户端一直发送,但是在本地服务器就是接收不到数据,最恶心的是根本不报错,所以根本不知道错在了哪。在讲过查阅资料后,终于解决了该问题,

    1.首先,要先将树莓派和本地服务器的防火墙都关掉。

    2.其次就是代码中的一些参数需要注意,具体代码如下:

    package UDPTest;
    
    import java.net.DatagramPacket;  
    import java.net.DatagramSocket;  
    import java.net.InetAddress;  
     
    public class Client {  
       public static void main(String[] args) {  
           try {  
               // 创建发送方的套接字,IP默认为本地,端口号随机  
               DatagramSocket sendSocket = new DatagramSocket();  
     
               // 确定要发送的消息:  
               String mes = "你好!接收方!";  
     
               // 由于数据报的数据是以字符数组传的形式存储的,所以传转数据  
               byte[] buf = mes.getBytes();  
     
               // 确定发送方的IP地址及端口号,地址为本地机器地址  
               int port = 12306;  
    //这里填写的服务器的IP地址 InetAddress ip
    = InetAddress.getByName("192.168.43.57"); // 创建发送类型的数据报: DatagramPacket sendPacket = new DatagramPacket(buf, buf.length,ip, port); // 通过套接字发送数据: sendSocket.send(sendPacket); // 确定接受反馈数据的缓冲存储器,即存储数据的字节数组 byte[] getBuf = new byte[1024]; // 创建接受类型的数据报 DatagramPacket getPacket = new DatagramPacket(getBuf, getBuf.length); // 通过套接字接受数据 sendSocket.receive(getPacket); // 解析反馈的消息,并打印 String backMes = new String(getBuf, 0, getPacket.getLength()); System.out.println("接受方返回的消息:" + backMes); // 关闭套接字 sendSocket.close(); } catch (Exception e) { e.printStackTrace(); } } }

    接收端代码如下:

    package UDPTest;
    
    import java.net.DatagramPacket;  
    import java.net.DatagramSocket;  
    import java.net.InetAddress;  
    import java.net.SocketAddress;  
     
    public class Server {  
       public static void main(String[] args) {  
           try {  
               // 确定接受方的IP和端口号,IP地址为本地机器地址  
               InetAddress ip = InetAddress.getLocalHost();  
               int port = 12306;  
     
               // 创建接收方的套接字,并制定端口号和IP地址  
               DatagramSocket getSocket = new DatagramSocket(port, ip);  
     
               // 确定数据报接受的数据的数组大小  
               byte[] buf = new byte[1024];  
     
               // 创建接受类型的数据报,数据将存储在buf中  
               DatagramPacket getPacket = new DatagramPacket(buf, buf.length);  
     
               // 通过套接字接收数据  
               getSocket.receive(getPacket);  
     
               // 解析发送方传递的消息,并打印  
               String getMes = new String(buf, 0, getPacket.getLength());  
               System.out.println("对方发送的消息:" + getMes);  
     
               // 通过数据报得到发送方的IP和端口号,并打印  
               InetAddress sendIP = getPacket.getAddress();  
               int sendPort = getPacket.getPort();  
               System.out.println("对方的IP地址是:" + sendIP.getHostAddress());  
               System.out.println("对方的端口号是:" + sendPort);  
     
               // 通过数据报得到发送方的套接字地址  
               SocketAddress sendAddress = getPacket.getSocketAddress();  
     
               // 确定要反馈发送方的消息内容,并转换为字节数组  
               String feedback = "接收方说:我收到了!";  
               byte[] backBuf = feedback.getBytes();  
     
               // 创建发送类型的数据报  
               DatagramPacket sendPacket = new DatagramPacket(backBuf,  
                       backBuf.length, sendAddress);  
     
               // 通过套接字发送数据  
               getSocket.send(sendPacket);  
     
               // 关闭套接字  
               getSocket.close();  
           } catch (Exception e) {  
               e.printStackTrace();  
           }  
       }  
    }  

    注:在接收端只需要填写接收的端口号即可,前提是服务器端 和客户端端口一致,并且没有被占用。

    在启动时要先启动服务端,在启动客户端。

    其次就是注意其中DatagramPacket的构造参数的问题。

    运行程序结果如下:

    客户端:

     

     

    接收端:

    如果还有别的什么问题,请留言联系。

     

    转载于:https://www.cnblogs.com/ljysy/p/10964530.html

    展开全文
  • 学习目标: 1.用C#编写一个命令行/控制台...1.,用Advanced_IP_Scanner查看到一个名字叫Raspberry Pi的计算机名称,就是树莓派的,记下他的IP地址 2.Xshell里面新建会话pi2-Android 输入用户名和密码后保存并连接 编
  • 文章目录C#写一个控制台程序作为客户端 C#写一个控制台程序作为客户端 1、vs2015professinoal里新建一个C#控制台应用程序 问题记录:在我创建工程时有一个问题,创建好了之后会窗口提示错误 Visual Studio 遇到了...
  • 树莓派通信程序

    2014-06-26 22:38:29
    该程序运行在树莓派上,主要功能是把收到的UDP消息通过树莓派自带串口发给下位机,同时把串口收到的数据通过UDP发送出去,使用threading模块启动两个线程,互不干涉,可以在此基础上更改实现各种功能。
  • 一个是树莓派,一个是买台能刷LEDE的路由器。预算500RMB以内吧。 不知道哪一种选择,更适合加速游戏呢? 谢谢。</p><p>该提问来源于开源项目:wangyu-/tinyfecVPN</p></div>
  • 树莓派串口通信

    2018-09-06 15:06:14
    使用树莓派实现串口数据转UDP数据通信的代码及脚本,亲测可靠
  • 树莓派平台简介

    千次阅读 2017-01-09 20:29:59
    为提升大规模网络的整体运行性能,对网络的运行质量需要进行有效的测量,可以使用...树莓派功能强大、设备小巧、可整合丰富的Linux类软件,可以方便的在节点作为探针发起主动的TCP\UDP网络性能测试。使用树莓派网络探针
  • (三)树莓派系统配置 装系统,连接电脑,ssh,wifi...... (四)GPIO驱动小车 GPIO分类,控制方案,驱动模块 (五)Android安卓控制 安装环境略过,代码 (六)调用摄像头 picamera部分用法 (七)图像处理...
  • 树莓派摄像头及视频

    千次阅读 2016-01-18 13:54:12
    参数:  镜头:1/4 5M  光圈:2.9  焦距:3.29  视场角:72.4度  硬件连接:  1. 软排线,90度垂直连接器,HDMI口旁边那个。连接时触点一侧朝向HDMI...C:\Program Files (x86)\VideoLAN\VLC>vlc udp://@:8
  • Linux 树莓派平台简介

    2017-01-10 21:58:54
    为提升大规模网络的整体运行性能,对网络的运行质量需要进行有效的测量,可以使用...树莓派功能强大、设备小巧、可整合丰富的Linux类软件,可以方便的在节点作为探针发起主动的TCP\UDP网络性能测试。使用树莓派网络探针
  • 树莓派网线直连

    2016-10-30 17:20:47
    树莓派网线直连电脑,电脑设置自动获取IP,使用arp -a命令可以查找到网络上的所有IP,对照自身IP即可以知道对方IP及掩码 然后可以UDP发送设置WIFI命令:  var obj={};  obj._CMD_='WIFI';  obj.SSID= “” ...
  • 树莓派4b外置wifi

    千次阅读 2020-06-29 00:13:17
    树莓派4b的性能还是不错的。但是本来想写一个局域网串流的程序,发现UDP往局域网里发包发不动,特别是跟IO一起使用,网速更不稳定ping网关经常好几百ms。 于是买了一个USB的wifi增强一下wifi。 首先让pi的用户拥有...

空空如也

1 2 3 4 5
收藏数 83
精华内容 33
关键字:

udp 树莓派