首页 > 其他分享 >8266sg90舵机+WPF上位机

8266sg90舵机+WPF上位机

时间:2023-07-23 15:45:34浏览次数:34  
标签:u8g2 舵机 void bytes System using WPF buf 8266sg90

上位机可以通过串口控制舵机、蜂鸣器。

示例:
image-20230723151914883
image-20230723152036627

Esp8266部分

基于Arduino,依赖库:U8g2、Servo。

接线引脚看代码哈。

#include <Arduino.h>
#include <Servo.h>
#include <U8g2lib.h>

/***OLED 引脚 */
#define SCL 5  /* 时钟引脚*/
#define SDA 4  /* 数据引脚*/
#define RES 14 /* 复位引脚*/
#define DC 12  /* 命令控制引脚*/
#define CS 13  /* 片选引脚*/

/***蜂鸣器 引脚 */
#define BuzzerPin 15

U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/SCL, /* data=*/SDA, /* cs=*/CS, /* dc=*/DC, /* reset=*/RES);
Servo sg90;
/**
 * @brief 初始化OLED屏幕
 *
 */
void OLED_Init(void);
/**
 * @brief OLED显示SG90的角度
 *
 * @param i 角度 0~180
 */
void OLED_SG90(int i);

/**
 * @brief 串口接收
 */
void Serial_Recv(void);

/**
 * @brief 设置SG90舵机角度
 *
 * @param angle 角度 0-180
 */
void Set_SG90(int angle);

/**
 * @brief 蜂鸣器初始化
 *
 */
void Init_Buzzer(void);

/**
 * @brief 设置蜂鸣器
 *
 * @param mode 模式
 * 1 -> di(短)
 * 2 -> di~(长)
 * 3 —> di~di(短、急促的)
 */
void Set_Buzzer(int mode);

void setup()
{
  Serial.begin(115200);
  OLED_Init();

  sg90.attach(2);
  Set_SG90(90);
  OLED_SG90(90);

  Init_Buzzer();
  Set_Buzzer(2);
}

void loop()
{
  Serial_Recv();
}

char buf[4] = {0x00};
void Serial_Recv()
{
  if (Serial.available() >= 4)
  {
    Serial.readBytes(buf, 4);

    /***报文: FF __ __ FE */
    if (buf[0] == 0xFF && buf[3] == 0xFE)
    {
      if (buf[1] == 0x00)
      {
        /**舵机: FF 00 __ FE*/
        Set_SG90(buf[2]);
        OLED_SG90(buf[2]);
        Serial.write(buf, 4);
        delay(20);
      }
      else if (buf[1] == 0x01)
      {
        /** 蜂鸣器: FF 01 __ FE*/
        Set_Buzzer(buf[2]);
        Serial.write(buf, 4);
        delay(20);
      }
    }
  }
}

void Set_SG90(int angle)
{
  sg90.write(angle);
}

char oled_buf[4];
void OLED_SG90(int i)
{
  u8g2.setCursor(50, 40);
  sprintf(oled_buf, "%03d", i);
  u8g2.print(oled_buf);
  u8g2.sendBuffer();
}

void OLED_Init(void)
{
  u8g2.begin();            // 初始化 u8g2
  u8g2.disableUTF8Print(); // 关闭UTF-8模式

  u8g2.setFont(u8g2_font_unifont_t_chinese2); // use chinese2 for all the glyphs of "你好世界"
  u8g2.setFontDirection(0);
  u8g2.clearBuffer();

  u8g2.setCursor(0, 15);
  u8g2.print("SG90:");

  u8g2.setCursor(20, 40);
  u8g2.print("P:");

  u8g2.sendBuffer();
}

void Init_Buzzer(void)
{
  pinMode(BuzzerPin, OUTPUT);
}

void Set_Buzzer(int mode)
{
  switch (mode)
  {
  case 0:
    digitalWrite(BuzzerPin, HIGH);
    delay(100);
    digitalWrite(BuzzerPin, LOW);
    break;
  case 1:
    digitalWrite(BuzzerPin, HIGH);
    delay(300);
    digitalWrite(BuzzerPin, LOW);
    break;
  case 2:
    digitalWrite(BuzzerPin, HIGH);
    delay(50);
    digitalWrite(BuzzerPin, LOW);
    delay(50);
    digitalWrite(BuzzerPin, HIGH);
    delay(50);
    digitalWrite(BuzzerPin, LOW);
    break;
  default:
    break;
  }
}

上位机部分

串口数据帧可以看esp代码

MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:local="clr-namespace:WpfApp1"
  mc:Ignorable="d"
  Title="MainWindow"
  Height="250"
  Width="800">
  <StackPanel>
    <StackPanel HorizontalAlignment="Left"
      Orientation="Horizontal"
      Height="30"
      Margin="50 50 0 0">
      <Label Content="舵机:" />
      <Slider x:Name="slider"
        HorizontalAlignment="Left"
        Margin="10 0 0 0 "
        Minimum="0"
        Maximum="180"
        PreviewMouseUp="slider_MouseUp"
        Width="604"
        Value="{Binding Pos}"
        Height="23">
      </Slider>

      <Label x:Name="label"
        Content="{Binding Pos, StringFormat={}{0}d}"
        HorizontalAlignment="Left"
        Height="23"
        Width="40"
        Margin="10 0 0 0 "
        VerticalAlignment="Top" />

    </StackPanel>

    <StackPanel Orientation="Horizontal"
      HorizontalAlignment="Left"
      Margin="50 20 0 0">
      <Label Content="蜂鸣器:" />



      <Button  Height="25"
        Width="70"
        Margin="10 0 0 0 "
        Content="Mode 1"
        Click="btn_buzz_mode1"/>

      <Button  Height="25"
        Width="70"
        Margin="10 0 0 0 "
        Content="Mode 2"
        Click="btn_buzz_mode2"/>

      <Button  Height="25"
        Width="70"
        Margin="10 0 0 0 "
        Content="Mode 3"
        Click="btn_buzz_mode3" />       

      <Button  Height="25"
        Width="70"
        Margin="10 0 0 0 "
        Content="Mode 4"
        Click="btn_buzz_mode4" />

    </StackPanel>

  </StackPanel>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO.Ports;
using System.Threading;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        private SerialPort serialPort;
        private MainViewModel m;
        public MainWindow()
        {
            InitializeComponent();
            m = new MainViewModel();
            this.DataContext = m;

            // 初始化串口设置
            serialPort = new SerialPort("COM8", 115200); // 替换为实际的串口号和波特率

            serialPort.DataReceived += SerialPort_DataReceived;  // 接收回调
            serialPort.Open();
            if (serialPort.IsOpen == false)
            {
                Debug.WriteLine("串口打开失败,请检查是否有占用!");
            }
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // 处理接收到的数据
            byte[] buffer = new byte[serialPort.BytesToRead];
            serialPort.Read(buffer, 0, buffer.Length);

            string receivedData = BitConverter.ToString(buffer).Replace("-", " ");
            Dispatcher.Invoke(() =>
            {
                //ReceivedDataTextBox.Text +=  + Environment.NewLine;
                Debug.WriteLine(receivedData);
            });
        }



        private void slider_MouseUp(object sender, MouseButtonEventArgs e)
        {

            byte[] bytes = new byte[4];
            bytes[0] = 0xFF;
            bytes[1] = 0x00;
            bytes[2] = BitConverter.GetBytes(m.Pos)[0];
            bytes[3] = 0xFE;
            serialPort.Write(bytes, 0, bytes.Length);
            Thread.Sleep(30);
        }

        private void btn_buzz_mode1(object sender, RoutedEventArgs e)
        {
            byte[] bytes = new byte[4];
            bytes[0] = 0xFF;
            bytes[1] = 0x01;
            bytes[2] = 0x00;
            bytes[3] = 0xFE;
            serialPort.Write(bytes, 0, bytes.Length);
            Thread.Sleep(30);
        }
        private void btn_buzz_mode2(object sender, RoutedEventArgs e)
        {
            byte[] bytes = new byte[4];
            bytes[0] = 0xFF;
            bytes[1] = 0x01;
            bytes[2] = 0x01;
            bytes[3] = 0xFE;
            serialPort.Write(bytes, 0, bytes.Length);
            Thread.Sleep(30);
        }

        private void btn_buzz_mode3(object sender, RoutedEventArgs e)
        {
            byte[] bytes = new byte[4];
            bytes[0] = 0xFF;
            bytes[1] = 0x01;
            bytes[2] = 0x02;
            bytes[3] = 0xFE;
            serialPort.Write(bytes, 0, bytes.Length);
            Thread.Sleep(30);
        }

        private void btn_buzz_mode4(object sender, RoutedEventArgs e)
        {
            byte[] bytes = new byte[4];
            bytes[0] = 0xFF;
            bytes[1] = 0x01;
            bytes[2] = 0x03;
            bytes[3] = 0xFE;
            serialPort.Write(bytes, 0, bytes.Length);
            Thread.Sleep(30);
        }
    }
}

MainViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp1
{
    internal class MainViewModel : INotifyPropertyChanged
    {
        private int pos;

        public int Pos
        {
            get => pos;
            set
            {

                this.pos = value;
                RaisePropertyChanged("Pos");
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

标签:u8g2,舵机,void,bytes,System,using,WPF,buf,8266sg90
From: https://www.cnblogs.com/xxing/p/17575082.html

相关文章

  • 【雕爷学编程】Arduino动手做(167)---MG996R金属齿轮舵机
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试多做实验,不管成功与否,都会记录下来——小小的进步或是搞不掂的问题......
  • WPF AsyncLocal 为 null 的错误 、 AsyncLocal 在WPF中的使用问题
    前言:  想载WPF中使用AsyncLocal下,发现这里面有个巨坑。参考链接  标题为AsyncLocalinWPFisnullafterfirstsetonthesamethread  AsyncLocl变量在程序初始化时设置,主窗口加载Load事件之前都还有,Load事件执行完后就,清空了ExecutionContext。示例  ......
  • WPF .net6 自定义启动入口 、 自定义Main函数、自定义 STAThread 方法
    前言:  为了解决程序开启自启动问题参考资料  CustomEntryPointsinWPFon.NETCore链接https://blog.magnusmontin.net/2020/01/31/custom-entry-point-wpf-net-core/  CreatingacustomMainmethodinaWPFapplication链接https://www.meziantou.net/creat......
  • WPF 开机启动
    前言:  熬了几夜学到点东西,就以为翻越了一座山,艹,前面还有无数个日日夜夜。修改注册表  Registry.CurrentUser.OpenSubKey(“SOFTWARE\Microsoft\Windows\CurrentVersion\Run”,true),给当前用户设置开机启动    设置此项目,程序不需要使用管理员权限启动。  Registr......
  • 【花雕动手做】尝试使用不同舵机来控制中空旋转平台(机械臂底盘)
    盆友送了一个机器人的关节,全金属结构,做工比较精致,如图经查这个金属关节来源于克鲁泽Cruzr人形机器人,它总共有15个自由度,其中2个就是机身关节,用于连接机身与仿生机械手臂。关键词:中空旋转平台,金属云台,机械臂旋转底盘,机器人关节,中空金属转台中空旋转平台通过电机(舵机)驱动,实......
  • WPF 和 JavaFX
    WPF和JavaFX:跨平台图形界面开发的两种选择在软件开发中,图形界面是用户与程序交互的重要组成部分。为了提供良好的用户体验,开发人员需要选择一种先进的界面开发技术。本文将介绍两种跨平台图形界面开发技术:WPF(WindowsPresentationFoundation)和JavaFX,并提供代码示例来说明它们的......
  • WPF调试软件窗口顶部工具栏的开起与关闭
    WPF调试软件窗口顶部工具栏的开起与关闭应用内工具栏可以实现元素选取,XAML热重载,绑定异常检测等功能工具栏->选项......
  • 【雕爷学编程】Arduino动手做(164)---Futaba S3003舵机模块3
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试多做实验,不管成功与否,都会记录下来——小小的进步或是搞不掂的问题......
  • WPF版本发布流程
    前言使用工具:MicrosoftVisualStudio2012框架版本:.NETFramework4.5一、WPF发布程序的教程方法1.进入项目目录,右键点击属性 (右键:属性=>发布)  2.填写程序发布路径  本地发布选择【文件系统】、填入发布路径即可下一步(可以新建1个文件夹)。3.选择程序文件(发布......
  • 【雕爷学编程】Arduino动手做(164)---Futaba S3003舵机模块2
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试多做实验,不管成功与否,都会记录下来——小小的进步或是搞不掂的问题......