与狼共舞——为Go2安装M416全自动水弹枪(二)

导语

  作为本系列的开篇,有必要先做些约定:

  • 以后的内容仅提供核心功能的代码,尽可能简洁,毕竟每个狗主都会有自己的想法,会添加自己的功能,写太多不容易整合,更何况我也没做什么复杂功能。
  • 提供的代码片段不进行过多解释,程序语言也是语言,“领会精神“”就好。

  • 不管是硬件设计还是软件编程部分,咱遵循三哥军工的设计思路,能依赖现有软件功能的就绝不自己编码,能购买的电子模块绝不自己动手制作。
  • 机器人操作系统采用Ros2 Foxy,软件编程使用python语言,硬件编程c语言,操作系统Ubuntu 20.04
     

 

功能

  这里的功能仅指与架枪相关的功能。(水弹枪是儿子友情赞助的,请勿对人射击。)

  • 通过3D打印机打印支架和电器盒子,固定枪和电路板。
  • 由go2的扩展坞发送UDP广播消息给控制电路,击发开火。
  • 编程实现原厂遥控器的向上按钮作为开火键。
  • cv2实现一个简单的人脸识别系统。
  • 实现一个deepseek agent功能,让go2能理解你发出的指令,并按照你的指令执行任务(如,找到张三,立即开火。 或者 打个招呼 ...)

go2(2)
 

硬件

  先上图,实物接线图:

gunctl
  
  图中的板子,都是淘宝上淘来的,其中控制板150元左右、DCDC模块2元左右,电子开关不到1元。

1.水弹枪

  《绝地求生》装备M416全自动步枪,许多年前买的,不记得多少钱了,原先还有很多附件,都丢光了。破是破了点,但还能打,玩起来很解压。靠2节18650电池驱动(3.7+3.7V=7.4V),时间久了,电池也已经失效,因此,从go2的12v输出取电,通过一个可调DC-DC降压模块给枪供电。

2.控制板

  以前买的一块开发板,STM32F103C8T6芯片+W5500以太网模块+2路CAN+2路485,价值150元左右,其实控制枪不用这么多功能,只要有W5500以太网模块和GPIO口输出的板子就行,GPIO口控制电子开关给枪供电。

3.DCDC模块

  把go2的12V直流电降为7.4V。

4.电子开关

  接收GPIO控制信号,打开或关闭枪的电源,枪有电就发射。(枪的扳机被我绑在击发位置)
 

控制程序

  • STM32CubeMX

gunctl1

  • 移植W5500驱动库
    -- 1. 下载W5500驱动库,gitee下载地址github下载地址。将ioLibrary_Driver目录拷贝到你的工程下面。
    -- 2. 将ioLibrary_Driver\Ethernet目录下的3个文件及其头文件——w5500.c,wizchip_conf.c,socket.c,添加到你的工程中。

  • 控制程序
      该部分代码使用了FreeRTOS操作系统,监听UDP 5001端口,当接收到消息含有fire字符串是,PB7口持续1秒的高电平。也就是说当收到UDP消息fire的时候,M416枪开火1秒。

/* USER CODE END Header_StartTaskSendMsg */
void StartTaskGetMsg(void *argument)
{
  /* USER CODE BEGIN StartTaskSendMsg */
  /* Infinite loop */
  for(;;)
  {
		do_udp();	
		
		if (fired == 1)
		{
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
			osDelay(1000);
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_7);
			fired = 0;			
		}
		
    osDelay(1000);
		
  }
  /* USER CODE END StartTaskSendMsg */
}

myudp.c程序中定义了W5500的网络信息,监听端口、ip地址等,并处理接收到的消息。
myudp.h

#ifndef MYUDP_H
#define MYUDP_H

#include "myudp.h"
#include "main.h"
#include "w5500.h"
#include "socket.h"
#include "wizchip_conf.h"
#include "spi.h"
#include <string.h>

#define SOCK_UDPS 2

extern uint8_t buff[128];
extern uint8_t UDP_send_buff[128];
extern uint8_t remote_ip[4];
extern uint16_t remote_port;

void UDPinit(void);
void do_udp(void);
void udp_send(uint8_t* data, uint8_t len);
void Analysis(uint8_t *buf);
#endif // MYUDP_H

在这里可以修改你的IP地址,监听端口,处理接收到的消息。
myudp.c


#include "myudp.h"
#include "main.h"
#include "w5500.h"
#include "socket.h"
#include "wizchip_conf.h"
#include "spi.h"
#include <string.h>

uint8_t buff[128];
uint8_t UDP_send_buff[128];

uint8_t remote_ip[4] = {255,255,255,255};
uint16_t remote_port = 8080;
//片选
void W5500_Select(void) {
    HAL_GPIO_WritePin(SCSn_GPIO_Port, SCSn_Pin, GPIO_PIN_RESET);
}
void W5500_Unselect(void) {
    HAL_GPIO_WritePin(SCSn_GPIO_Port, SCSn_Pin, GPIO_PIN_SET);
}
void W5500_Restart(void) {
    HAL_GPIO_WritePin(RSTn_GPIO_Port, RSTn_Pin, GPIO_PIN_RESET);
    HAL_Delay(1);  // delay 1ms
    HAL_GPIO_WritePin(RSTn_GPIO_Port, RSTn_Pin, GPIO_PIN_SET);
    HAL_Delay(1600);  // delay 1600ms
}

void W5500_ReadBuff(uint8_t* buff, uint16_t len) {
    HAL_SPI_Receive(&hspi2, buff, len, HAL_MAX_DELAY);
}

void W5500_WriteBuff(uint8_t* buff, uint16_t len) {
    HAL_SPI_Transmit(&hspi2, buff, len, HAL_MAX_DELAY);
}

uint8_t W5500_ReadByte(void) {
    uint8_t byte;
    W5500_ReadBuff(&byte, sizeof(byte));
    return byte;
}

void W5500_WriteByte(uint8_t byte) {
    W5500_WriteBuff(&byte, sizeof(byte));
}

//配置W5500网络信息
wiz_NetInfo gSetNetInfo = {
  .mac  = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11},
  .ip   = {192, 168, 123, 55},
  .sn   = {255, 255, 255, 0},
  .gw   = {192, 168, 123, 1},
  .dns  = {144, 144, 144, 144},
  .dhcp = NETINFO_STATIC};

wiz_NetInfo gGetNetInfo;

enum Status
{
  Failed = 0,
  Success = 1
};

/**
 * @brief valid the result of set net info
 * @return 1: Success
 *         0: Failed
*/
uint8_t validSetNetInfoResult(wiz_NetInfo* _set, wiz_NetInfo* _get)
{
  return (!memcmp(_set, _get, sizeof(wiz_NetInfo)));  // if same, memcmp return 0
}


void UDPinit(void)
{
  reg_wizchip_cs_cbfunc(W5500_Select, W5500_Unselect);
  reg_wizchip_spi_cbfunc(W5500_ReadByte, W5500_WriteByte);

  W5500_Restart();  // hardware restart through RESET pin

  ctlnetwork(CN_SET_NETINFO, (void*)&gSetNetInfo);  // set net info
  // maybe need delay
  ctlnetwork(CN_GET_NETINFO, (void*)&gGetNetInfo);  // get net info

  // W5500 has 8 channel, 32k buffer, 2 means 2KBytes
  uint8_t buffer_size_8channel_tx_rx[16] = {2, 2, 2, 2, 2, 2, 2, 2,  // 8 channel tx
                                            2, 2, 2, 2, 2, 2, 2, 2}; // 8 channel rx
  if(ctlwizchip(CW_INIT_WIZCHIP,(void*)buffer_size_8channel_tx_rx))
  {
    // failed
    
  }

  uint8_t sta = getSn_SR(SOCK_UDPS);
  if(sta == SOCK_CLOSED)
  {
    socket(SOCK_UDPS, Sn_MR_UDP, 5001, 0);
  }
  HAL_Delay(100);

}


void do_udp(void)
{                                                              
	uint16_t len=0;	
	switch(getSn_SR(SOCK_UDPS))       /*获取socket的状态*/
	{
		case SOCK_CLOSED:                 /*socket处于关闭状态*/
			socket(SOCK_UDPS,Sn_MR_UDP,5001,0);    /*初始化socket*/
		  break;
		
		case SOCK_UDP:      /*socket初始化完成*/
			HAL_Delay(10);  
			if(getSn_IR(SOCK_UDPS) & Sn_IR_RECV) //检查是否有接收中断
			{
				setSn_IR(SOCK_UDPS, Sn_IR_RECV);  /*清接收中断*/
			}
			if((len=getSn_RX_RSR(SOCK_UDPS))>0)  /*接收到数据*/
			{
				recvfrom(SOCK_UDPS,buff, len, remote_ip,&remote_port);               /*W5500接收计算机发送来的数据W5500接收计算机发送来的数据,并获取发送方的IP地址和端口号*/
				sendto(SOCK_UDPS,buff,len-8, remote_ip, remote_port);                /*W5500把接收到的数据发送*/
        Analysis(buff);//分析数据
        memset(buff, 0, sizeof(buff));
			}
			break;
	}
}


void udp_send(uint8_t* data,uint8_t len)
{
  sendto(SOCK_UDPS, data, len, remote_ip, remote_port);
  memset(data, 0, len);
}

void SystemReset() {
    __HAL_RCC_BACKUPRESET_FORCE(); // 强制备份域复位
    __HAL_RCC_BACKUPRESET_RELEASE(); // 释放备份域复位
    NVIC_SystemReset(); // 发起系统复位
}

void Analysis(uint8_t *buf)
{
	char * gun = "fire";
	char * result = strstr((char*)buf, gun);
	if (result != NULL)
	{
		fired =1;		
		return;
	}
	
	char * devreset ="reset";
	result = strstr((char*)buf, devreset);
	if (result != NULL)
	{
			SystemReset();
			return;
	}
}

 

待续

  预祝您,成功将以上代码烧写进你的板子中。接下来,我们开始给go2扩展坞写ROS2程序,让它能够通过原厂遥控器击发开火功能。

posted @ 2025-10-05 05:10  鼻涕鱼  阅读(6)  评论(0)    收藏  举报