最近发现网上有人做桌面机器人,正好自己也有材料,就复刻了一个,通过手机APP遥控,可以实现各种表情以及动作,还有各种语音功能,下方有演示视频。有全套资料包括,SW建模,PCB文件,APP安装包,所需各种材料清单及店铺,keil代码等等,需要资料可联系1090632294@qq.com(送两句祝福语,免费分享源码)
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "OLED_Data.h"
#include "SG90.h"
#include "Serial.h"
#include "string.h"
float Angle;
uint8_t SG90_Status; //舵机状态
uint8_t Face_Status; //脸模显示状态
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
SG90_Init(); //舵机初始化
Serial_Init(); //串口初始化
OLED_ShowImage(0,0,128,64,FaceDou); //开机显示表情
OLED_Update();
Delay_ms(1000);
while (1)
{
if (Serial_RxFlag == 1) //串口接受数据包标志为1时,接收到数据
{
if (strcmp(Serial_RxPacket, "Advance") == 0){SG90_Status =1;Face_Status =1;}
if (strcmp(Serial_RxPacket, "Retreat") == 0){SG90_Status =2;Face_Status =2;}
if (strcmp(Serial_RxPacket, "Right") == 0){SG90_Status =3;Face_Status =3;}
if (strcmp(Serial_RxPacket, "Left") == 0){SG90_Status =4;Face_Status =4;}
if (strcmp(Serial_RxPacket, "Down") == 0){SG90_Status =5;Face_Status =5;}
if (strcmp(Serial_RxPacket, "Up") == 0){SG90_Status =6;Face_Status =6;}
if (strcmp(Serial_RxPacket, "Hard") == 0){SG90_Status =7;Face_Status =7;}
if (strcmp(Serial_RxPacket, "Rock") == 0){SG90_Status =8;Face_Status =8;}
if (strcmp(Serial_RxPacket, "Sit") == 0){SG90_Status =9;Face_Status =9;}
if (strcmp(Serial_RxPacket, "Sit_Hard") == 0){SG90_Status =10;Face_Status =10;}
if (strcmp(Serial_RxPacket, "Advance_plus") == 0){SG90_Status =11;Face_Status =11;}
if (strcmp(Serial_RxPacket, "Retreat_plus") == 0){SG90_Status =12;Face_Status =12;}
if (strcmp(Serial_RxPacket, "Right_plus") == 0){SG90_Status =13;Face_Status =13;}
if (strcmp(Serial_RxPacket, "Left_plus") == 0){SG90_Status =14;Face_Status =14;}
if (strcmp(Serial_RxPacket, "Ass") == 0){SG90_Status =15;Face_Status =15;}
if (strcmp(Serial_RxPacket, "Dou") == 0){Face_Status =16;}
if (strcmp(Serial_RxPacket, "Crazy") == 0){Face_Status =17;}
Serial_RxFlag = 0;
}
switch(SG90_Status) //舵机状态选择
{
case 1: SG90_Advance();break;
case 2: SG90_Retreat();break;
case 3: SG90_TrunRight();break;
case 4: SG90_TrunLeft();break;
case 5: SG90_Down();break;
case 6: SG90_Up();break;
case 7: SG90_Hard();break;
case 8: SG90_Rock();break;
case 9: SG90_Sit();break;
case 10: SG90_SitHard();break;
case 11: SG90_CrazyAdvance();break;
case 12: SG90_CrazyRetreat();break;
case 13: SG90_CrazyTrunRight();break;
case 14: SG90_CrazyTrunLeft();break;
case 15: SG90_Ass();break;
}
switch(Face_Status) //脸模显示状态选择
{
case 1: OLED_ShowImage(0,0,128,64,FaceDou);OLED_Update();break;
case 2: OLED_ShowImage(0,0,128,64,FaceDou);OLED_Update();break;
case 3: OLED_ShowImage(0,0,128,64,FaceRight);OLED_Update();break;
case 4: OLED_ShowImage(0,0,128,64,FaceLeft);OLED_Update();break;
case 5: OLED_ShowImage(0,0,128,64,FaceSleep);OLED_Update();break;
case 6: OLED_ShowImage(0,0,128,64,FaceBlock);OLED_Update();break;
case 7: OLED_ShowImage(0,0,128,64,FaceDou);OLED_Update();break;
case 8: OLED_ShowImage(0,0,128,64,FaceCry);OLED_Update();break;
case 9: OLED_ShowImage(0,0,128,64,FaceDou);OLED_Update();break;
case 10: OLED_ShowImage(0,0,128,64,FaceDou);OLED_Update();break;
case 11: OLED_ShowImage(0,0,128,64,FaceEvil);OLED_Update();break;
case 12: OLED_ShowImage(0,0,128,64,FaceEvil);OLED_Update();break;
case 13: OLED_ShowImage(0,0,128,64,FaceEvil);OLED_Update();break;
case 14: OLED_ShowImage(0,0,128,64,FaceEvil);OLED_Update();break;
case 15: OLED_ShowImage(0,0,128,64,FaceAss);OLED_Update();break;
case 16: OLED_ShowImage(0,0,128,64,FaceDou);OLED_Update();break;
case 17: OLED_ShowImage(0,0,128,64,FaceEvil);OLED_Update();break;
}
}
}
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
/**
* º¯ Êý£º´®¿Ú³õʼ»¯
* ²Î Êý£ºÎÞ
* ·µ »Ø Öµ£ºÎÞ
*/
void Serial_Init(void)
{
/*¿ªÆôʱÖÓ*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //¿ªÆôUSART1µÄʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //¿ªÆôGPIOAµÄʱÖÓ
/*GPIO³õʼ»¯*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //½«PA9Òý½Å³õʼ»¯Îª¸´ÓÃÍÆÍìÊä³ö
/*USART³õʼ»¯*/
USART_InitTypeDef USART_InitStructure; //¶¨Òå½á¹¹Ìå±äÁ¿
USART_InitStructure.USART_BaudRate = 9600; //²¨ÌØÂÊ
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //Ó²¼þÁ÷¿ØÖÆ£¬²»ÐèÒª
USART_InitStructure.USART_Mode = USART_Mode_Tx; //ģʽ£¬Ñ¡ÔñΪ·¢ËÍģʽ
USART_InitStructure.USART_Parity = USART_Parity_No; //ÆæÅ¼Ð£Ñ飬²»ÐèÒª
USART_InitStructure.USART_StopBits = USART_StopBits_1; //ֹͣλ£¬Ñ¡Ôñ1λ
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //×Ö³¤£¬Ñ¡Ôñ8λ
USART_Init(USART1, &USART_InitStructure); //½«½á¹¹Ìå±äÁ¿½»¸øUSART_Init£¬ÅäÖÃUSART1
/*USARTʹÄÜ*/
USART_Cmd(USART1, ENABLE); //ʹÄÜUSART1£¬´®¿Ú¿ªÊ¼ÔËÐÐ
}
/**
* º¯ Êý£º´®¿Ú·¢ËÍÒ»¸ö×Ö½Ú
* ²Î Êý£ºByte Òª·¢Ë͵ÄÒ»¸ö×Ö½Ú
* ·µ »Ø Öµ£ºÎÞ
*/
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte); //½«×Ö½ÚÊý¾ÝдÈëÊý¾Ý¼Ä´æÆ÷£¬Ð´ÈëºóUSART×Ô¶¯Éú³ÉʱÐò²¨ÐÎ
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //µÈ´ý·¢ËÍÍê³É
/*Ï´ÎдÈëÊý¾Ý¼Ä´æÆ÷»á×Ô¶¯Çå³ý·¢ËÍÍê³É±ê־룬¹Ê´ËÑ»·ºó£¬ÎÞÐèÇå³ý±ê־λ*/
}
/**
* º¯ Êý£º´®¿Ú·¢ËÍÒ»¸öÊý×é
* ²Î Êý£ºArray Òª·¢ËÍÊý×éµÄÊ×µØÖ·
* ²Î Êý£ºLength Òª·¢ËÍÊý×éµÄ³¤¶È
* ·µ »Ø Öµ£ºÎÞ
*/
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i ++) //±éÀúÊý×é
{
Serial_SendByte(Array[i]); //ÒÀ´Îµ÷ÓÃSerial_SendByte·¢ËÍÿ¸ö×Ö½ÚÊý¾Ý
}
}
/**
* º¯ Êý£º´®¿Ú·¢ËÍÒ»¸ö×Ö·û´®
* ²Î Êý£ºString Òª·¢ËÍ×Ö·û´®µÄÊ×µØÖ·
* ·µ »Ø Öµ£ºÎÞ
*/
void Serial_SendString(char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i ++)//±éÀú×Ö·ûÊý×飨×Ö·û´®£©£¬Óöµ½×Ö·û´®½áÊø±ê־λºóÍ£Ö¹
{
Serial_SendByte(String[i]); //ÒÀ´Îµ÷ÓÃSerial_SendByte·¢ËÍÿ¸ö×Ö½ÚÊý¾Ý
}
}
/**
* º¯ Êý£º´Î·½º¯Êý£¨ÄÚ²¿Ê¹Óã©
* ·µ »Ø Öµ£º·µ»ØÖµµÈÓÚXµÄY´Î·½
*/
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1; //ÉèÖýá¹û³õֵΪ1
while (Y --) //Ö´ÐÐY´Î
{
Result *= X; //½«XÀ۳˵½½á¹û
}
return Result;
}
/**
* º¯ Êý£º´®¿Ú·¢ËÍÊý×Ö
* ²Î Êý£ºNumber Òª·¢Ë͵ÄÊý×Ö£¬·¶Î§£º0~4294967295
* ²Î Êý£ºLength Òª·¢ËÍÊý×ֵij¤¶È£¬·¶Î§£º0~10
* ·µ »Ø Öµ£ºÎÞ
*/
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i ++) //¸ù¾ÝÊý×Ö³¤¶È±éÀúÊý×ÖµÄÿһλ
{
Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); //ÒÀ´Îµ÷ÓÃSerial_SendByte·¢ËÍÿλÊý×Ö
}
}
/**
* º¯ Êý£ºÊ¹ÓÃprintfÐèÒªÖØ¶¨ÏòµÄµ×²ãº¯Êý
* ²Î Êý£º±£³ÖÔʼ¸ñʽ¼´¿É£¬ÎÞÐè±ä¶¯
* ·µ »Ø Öµ£º±£³ÖÔʼ¸ñʽ¼´¿É£¬ÎÞÐè±ä¶¯
*/
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch); //½«printfµÄµ×²ãÖØ¶¨Ïòµ½×Ô¼ºµÄ·¢ËÍ×Ö½Úº¯Êý
return ch;
}
/**
* º¯ Êý£º×Ô¼º·â×°µÄprinfº¯Êý
* ²Î Êý£ºformat ¸ñʽ»¯×Ö·û´®
* ²Î Êý£º... ¿É±äµÄ²ÎÊýÁбí
* ·µ »Ø Öµ£ºÎÞ
*/
void Serial_Printf(char *format, ...)
{
char String[100]; //¶¨Òå×Ö·ûÊý×é
va_list arg; //¶¨Òå¿É±ä²ÎÊýÁбíÊý¾ÝÀàÐ͵ıäÁ¿arg
va_start(arg, format); //´Óformat¿ªÊ¼£¬½ÓÊÕ²ÎÊýÁÐ±íµ½arg±äÁ¿
vsprintf(String, format, arg); //ʹÓÃvsprintf´òÓ¡¸ñʽ»¯×Ö·û´®ºÍ²ÎÊýÁÐ±íµ½×Ö·ûÊý×éÖÐ
va_end(arg); //½áÊø±äÁ¿arg
Serial_SendString(String); //´®¿Ú·¢ËÍ×Ö·ûÊý×飨×Ö·û´®£©
}
/**
* º¯ Êý£º´®¿Ú·¢Ë͸¡µãÐÍÊý×Ö ¿É×Ô¶¯Ê¶±ðÕûÊýλÊý
* ²Î Êý£ºNumber Òª·¢Ë͵ÄÊý×Ö£¬·¶Î§£º
* ²Î Êý£ºFraLength ±£ÁôСÊýλÊý£¬·¶Î§£º0~10
* ·µ »Ø Öµ£ºÎÞ
*/
void Serial_SendFloatNum(double Number,int FraLength)
{
uint32_t PowNum, IntNum, FraNum,a;
/*ÌáÈ¡ÕûÊý²¿·ÖºÍСÊý²¿·Ö*/
IntNum = Number; //Ö±½Ó¸³Öµ¸øÕûÐͱäÁ¿£¬ÌáÈ¡ÕûÊý
a=IntNum;
Number -= IntNum; //½«NumberµÄÕûÊý¼õµô£¬·ÀÖ¹Ö®ºó½«Ð¡Êý³Ëµ½ÕûÊýʱÒòÊý¹ý´óÔì³É´íÎó
PowNum = Serial_Pow(10, FraLength); //¸ù¾ÝÖ¸¶¨Ð¡ÊýµÄλÊý£¬È·¶¨³ËÊý
FraNum = round(Number * PowNum); //½«Ð¡Êý³Ëµ½ÕûÊý£¬Í¬Ê±ËÄÉáÎåÈ룬±ÜÃâÏÔʾÎó²î
IntNum += FraNum / PowNum; //ÈôËÄÉáÎåÈëÔì³ÉÁ˽øÎ»£¬ÔòÐèÒªÔÙ¼Ó¸øÕûÊý
int datalength=0;
while(IntNum!=0)
{
datalength++;
IntNum=IntNum/10;//Ò»¹²Óм¸Î»ÕûÊý
} //´ËʱIntNumΪ0 ÐèÒªÖØÐ¸øIntNum¸³Öµ
IntNum=a;
Serial_SendNumber(IntNum,datalength);//·¢ËÍÕûÊý²¿·Ö
Serial_SendString(".");
Serial_SendNumber(FraNum,FraLength);//·¢ËÍСÊý²¿·Ö
}
表情
STM32机器人