初始提交:龙芯2K0300智能车卖家Demo完整代码
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# demo2
|
||||
add_executable(udp_receive udp_receive.cpp)
|
||||
|
||||
# 链接 OpenCV 库
|
||||
target_link_libraries(udp_receive common_lib ${OpenCV_LIBS})
|
||||
@@ -0,0 +1,104 @@
|
||||
'''
|
||||
Author: ilikara 3435193369@qq.com
|
||||
Date: 2025-03-11 03:00:45
|
||||
LastEditors: Ilikara 3435193369@qq.com
|
||||
LastEditTime: 2025-03-11 17:04:09
|
||||
FilePath: /2k300_smartcar/udp_receive/slider.py
|
||||
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
'''
|
||||
import tkinter as tk
|
||||
import socket
|
||||
import struct
|
||||
|
||||
# 配置参数
|
||||
TARGET_IP = "192.168.43.238" # 目标板卡IP
|
||||
TARGET_PORT = 8888 # 目标端口
|
||||
|
||||
|
||||
class UdpSliderApp:
|
||||
def __init__(self, master):
|
||||
self.master = master
|
||||
master.title("Dual Slider Control")
|
||||
|
||||
# 创建UDP socket
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
# 滑块1
|
||||
self.slider1_frame = tk.Frame(master)
|
||||
self.slider1_frame.pack(pady=10)
|
||||
self.label1 = tk.Label(self.slider1_frame, text="Angle: 0.00")
|
||||
self.label1.pack(side=tk.LEFT)
|
||||
self.slider1 = tk.Scale(
|
||||
self.slider1_frame,
|
||||
from_=-7.0, to=7.0,
|
||||
resolution=0.01,
|
||||
orient=tk.HORIZONTAL,
|
||||
length=300,
|
||||
command=lambda v: self.send_values()
|
||||
)
|
||||
self.slider1.pack(side=tk.LEFT)
|
||||
|
||||
# 滑块2
|
||||
self.slider2_frame = tk.Frame(master)
|
||||
self.slider2_frame.pack(pady=10)
|
||||
self.label2 = tk.Label(self.slider2_frame, text="Speed: 0.00")
|
||||
self.label2.pack(side=tk.LEFT)
|
||||
self.slider2 = tk.Scale(
|
||||
self.slider2_frame,
|
||||
from_=-20.0, to=20.0, # 示例范围可调
|
||||
resolution=0.1,
|
||||
orient=tk.HORIZONTAL,
|
||||
length=300,
|
||||
command=lambda v: self.send_values()
|
||||
)
|
||||
self.slider2.pack(side=tk.LEFT)
|
||||
|
||||
# 退出按钮
|
||||
self.exit_btn = tk.Button(
|
||||
master,
|
||||
text="Exit",
|
||||
command=master.quit,
|
||||
bg="#ff4444",
|
||||
fg="white"
|
||||
)
|
||||
self.exit_btn.pack(pady=20)
|
||||
|
||||
self.reset_btn = tk.Button(
|
||||
self.slider2_frame,
|
||||
text="Reset to 0",
|
||||
command=self.reset_slider2,
|
||||
bg="#ff6666",
|
||||
fg="white",
|
||||
width=8
|
||||
)
|
||||
self.reset_btn.pack(side=tk.LEFT, padx=10)
|
||||
|
||||
def send_values(self):
|
||||
"""打包并发送两个浮点数"""
|
||||
try:
|
||||
val1 = float(self.slider1.get())
|
||||
val2 = float(self.slider2.get())
|
||||
|
||||
# 更新标签
|
||||
self.label1.config(text=f"Angle: {val1:.2f}")
|
||||
self.label2.config(text=f"Speed: {val2:.2f}")
|
||||
|
||||
# 打包为网络字节序的两个float
|
||||
data = struct.pack('!ff', val1, val2) # !表示网络字节序
|
||||
|
||||
# 发送UDP数据
|
||||
self.sock.sendto(data, (TARGET_IP, TARGET_PORT))
|
||||
except Exception as e:
|
||||
print(f"发送错误: {str(e)}")
|
||||
|
||||
def reset_slider2(self):
|
||||
self.slider2.set(0.0) # 设置滑块物理位置
|
||||
self.label2.config(text="Slider2: 0.00") # 直接更新显示
|
||||
self.send_values() # 手动触发发送
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
app = UdpSliderApp(root)
|
||||
root.mainloop()
|
||||
app.sock.close()
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* @Author: ilikara 3435193369@qq.com
|
||||
* @Date: 2025-03-11 02:38:15
|
||||
* @LastEditors: ilikara 3435193369@qq.com
|
||||
* @LastEditTime: 2025-03-29 01:39:17
|
||||
* @FilePath: /2k300_smartcar/udp_receive/udp_receive.cpp
|
||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdint>
|
||||
#include <string.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <thread>
|
||||
|
||||
#include "MotorController.h"
|
||||
#include "PwmController.h"
|
||||
#include "GPIO.h"
|
||||
#include <iomanip>
|
||||
|
||||
cv::VideoCapture cap;
|
||||
|
||||
std::string directory = "./image";
|
||||
int saved_frame_count;
|
||||
void streamCapture(void)
|
||||
{
|
||||
cv::Mat frame;
|
||||
while (1)
|
||||
{
|
||||
cap.read(frame);
|
||||
if (frame.empty())
|
||||
{
|
||||
std::cerr << "Save Error: Frame is empty." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 构建文件名
|
||||
std::ostringstream filename;
|
||||
filename << directory << "/image_" << std::setw(5) << std::setfill('0') << saved_frame_count << ".jpg";
|
||||
|
||||
saved_frame_count++;
|
||||
// 保存图像
|
||||
cv::imwrite(filename.str(), frame);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GPIO mortorEN(73);
|
||||
MotorController *motorController[2] = {nullptr, nullptr};
|
||||
PwmController servo(1, 0);
|
||||
|
||||
void Init()
|
||||
{
|
||||
mortorEN.setDirection("out");
|
||||
mortorEN.setValue(1);
|
||||
const int pwmchip[2] = {8, 8};
|
||||
const int pwmnum[2] = {2, 1};
|
||||
const int gpioNum[2] = {12, 13};
|
||||
const int encoder_pwmchip[2] = {0, 3};
|
||||
const int encoder_gpioNum[2] = {75, 72};
|
||||
const int encoder_dir[2] = {1, -1};
|
||||
const unsigned int period_ns = 50000; // 20 kHz
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
motorController[i] = new MotorController(pwmchip[i], pwmnum[i], gpioNum[i], period_ns,
|
||||
0, 0, 0, 0,
|
||||
encoder_pwmchip[i], encoder_gpioNum[i], encoder_dir[i]);
|
||||
motorController[i]->updateduty(0);
|
||||
}
|
||||
|
||||
servo.setPeriod(3040000);
|
||||
servo.setDutyCycle(1520000);
|
||||
servo.enable();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// 打开默认摄像头(设备编号 0)
|
||||
cap.open(0);
|
||||
|
||||
// 检查摄像头是否成功打开
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
printf("无法打开摄像头\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cap.set(cv::CAP_PROP_FRAME_WIDTH, 320); // 宽度
|
||||
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 240); // 高度
|
||||
cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); // 视频流格式
|
||||
cap.set(cv::CAP_PROP_AUTO_EXPOSURE, -1); // 设置自动曝光
|
||||
|
||||
std::thread camworker = std::thread(streamCapture);
|
||||
|
||||
Init();
|
||||
|
||||
const int PORT = 8888;
|
||||
const int BUFFER_SIZE = 2 * sizeof(float);
|
||||
|
||||
// 创建UDP Socket
|
||||
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0)
|
||||
{
|
||||
std::cerr << "Socket creation failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 绑定地址和端口
|
||||
sockaddr_in server_addr{};
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
server_addr.sin_port = htons(PORT);
|
||||
|
||||
if (bind(sockfd, (sockaddr *)&server_addr, sizeof(server_addr)))
|
||||
{
|
||||
std::cerr << "Bind failed" << std::endl;
|
||||
close(sockfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 接收数据
|
||||
sockaddr_in client_addr{};
|
||||
socklen_t client_len = sizeof(client_addr);
|
||||
char buffer[BUFFER_SIZE];
|
||||
|
||||
while (true)
|
||||
{
|
||||
ssize_t bytes_received = recvfrom(
|
||||
sockfd,
|
||||
buffer,
|
||||
BUFFER_SIZE,
|
||||
0,
|
||||
(sockaddr *)&client_addr,
|
||||
&client_len);
|
||||
|
||||
if (bytes_received == BUFFER_SIZE)
|
||||
{
|
||||
// 解析第一个float
|
||||
uint32_t temp1;
|
||||
memcpy(&temp1, buffer, 4);
|
||||
temp1 = ntohl(temp1);
|
||||
float val1;
|
||||
memcpy(&val1, &temp1, 4);
|
||||
|
||||
// 解析第二个float
|
||||
uint32_t temp2;
|
||||
memcpy(&temp2, buffer + 4, 4);
|
||||
temp2 = ntohl(temp2);
|
||||
float val2;
|
||||
memcpy(&val2, &temp2, 4);
|
||||
|
||||
std::cout << "收到数据: "
|
||||
<< "滑块1=" << val1
|
||||
<< ", 滑块2=" << val2
|
||||
<< std::endl;
|
||||
|
||||
double servoduty_ns = (val1) / 100 * servo.readPeriod() + 1520000;
|
||||
servo.setDutyCycle(servoduty_ns);
|
||||
|
||||
motorController[0]->updateduty(val2);
|
||||
motorController[1]->updateduty(val2);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Invalid data size" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user