本帖最后由 RRoy 于 2024-9-19 16:36 编辑  
 
火星探测器作为一种遥控机器人,可以在不平坦的地形上运行。 
 
你有没有想过火星车是如何在火星崎岖的地形上航行的? 
 
秘密武器是巧妙的摇臂转向架(rocker-bogie)悬架系统。 
 
  
 
摇臂转向架悬架系统是一种特殊的车轮悬挂装置,最主要用于火星探测车等需要在复杂地形行驶的车辆上。 
 
它的主要特点有: 
- 结构简单:没有使用弹簧,而是通过特殊的机械结构来实现悬挂功能。
 - 六轮设计:通常有六个车轮,分为左右两组。
 - 摇臂(Rocker):每侧有一个大的摇臂连接车身和车轮。
 - 转向架(Bogie):每个摇臂末端连接一个小的转向架,转向架两端各有一个车轮。
 - 灵活性强:这种设计让车辆能够轻松越过高度达到车轮直径两倍的障碍物。
 - 稳定性好:即使在崎岖不平的地形上,也能保持车身相对平稳。
 - 适应性强:六个车轮可以独立运动,使车辆能够适应各种复杂地形。
 
 
  
简单来说,这种悬架系统就像是给车子装上了六条灵活的"腿",让它能够像昆虫一样轻松地爬过各种障碍物,非常适合在火星这样地形复杂的环境中使用。 
 
今天就和大家分享一辆3D打印的6轮摇臂转向架模型火星车。 
 
  
 
  
 
  
 
  
 
  
 
这个简单模型的主体部分是3D打印的,火星车使用 ESP12E 作为大脑,L293D 作为电机控制器。遥控器使用相同的 ESP12E 微控制器。 
 
除了可以用专用的遥控器控制,也可以使用手机应用程序控制。通过火星车上的传感器,可以在遥控器的OLED屏幕上看到实时的数据。流动站和遥控器之间的通信使用ESP-NOW协议。 
 
 
 
 
 
 
这个项目非常适合对机器人感兴趣的小伙伴,下面是具体的制作过程。 
 
ESP-NOW通讯 
ESP-NOW 是由乐鑫开发的通信协议,专为 ESP8266 和 ESP32 设备之间的低功耗点对点通信而设计,无需传统的 Wi-Fi 网络或互联网连接即可实现高效的数据交换。 
 
ESP-NOW 提供消息加密等基本安全功能,以保护传输的数据免受未经授权的访问。但是,需要注意的是,它无法提供与传统 Wi-Fi 网络中使用的更强大的协议(如 WPA2)相同的安全级别。 
 
简单来说,我们可以在不使用任何外部组件的情况下将数据从一个ESP板传输和接收到另一个ESP板。通过使用ESP-NOW,我们可以降低项目的总成本。 
所需组件 
  
 
 
- NodeMCU ESP8266 Breakout 开发板 X2
 - 模拟环境光线传感器(Arduino兼容)
 - L293D 电机驱动器
 - N20减速电机(60-100rpm
 - 3.7v 锂离子电池
 - 3.7v 至 5v 升压器
 - ESP12E X1 (以下组件适用于 DIY PCB)
 - 3.3V稳压器 AMS1117
 - 4 针母 JST 连接器、2 针母 JST 连接器 、4 针接头 X1
 - WS2812B neopixel X2
 - 阻容等其他组件
 
 
  
电路图 
  
 
在这个电路图中,使用了 ESP12E 微控制器作为大脑。它有足够的引脚来控制电机,并且有一个模拟引脚来检测传感器数据。选择此模块的另一个主要原因是因为就是WiFi,通过 WiFi 和 ESP-NOW 通信来控制此模块。 
 
为了控制电机,使用了 L293D 双通道 H 桥驱动器,一次双向控制两个电机。此外,还在电路中添加了电池充电模块。 
 
PCB设计 
  
 
  
 
  
 
  
 
在面包板上使用 NodeMCU 测试和验证电路后,最终确定 PCB 设计。 
 
  
 
将组件焊接在设计的 PCB 上非常容易,正常30分钟可以搞定。 
3D设计与安装 
接下来,就是为火星车造个身体了。 
 
3D模型文件下载:https://www.thingiverse.com/thing:6545945/files 
 
  
 
 
ESP32代码接收器代码 
 
			
			
			- //RX TEST
 - #include <ESP8266WiFi.h>
 - #include <espnow.h>
 - #include <FastLED.h>
 - #define NUM_LEDS 2
 - #define DATA_PIN 0
 - CRGB leds[NUM_LEDS];
 - const int motor1a = 2;
 - const int motor1b = 14;
 - const int motor2a = 13;
 - const int motor2b = 12;
 - 
 - uint8_t broadcastAddress[] = {0xAC, 0x0B, 0xFB, 0xCE, 0x8B, 0x16};//MASTER ESP8266 Board MAC Address:  AC:0B:FB:CF:16:91
 - String success;
 - 
 - 
 - typedef struct struct_message {
 -   int button;
 - } struct_message;
 - 
 - int IN_button_state;
 - int OUT_button_state;
 - 
 - 
 - // Create a struct_message called DHTReadings to hold sensor readings
 - struct_message outgoingmsg;
 - 
 - // Create a struct_message to hold incoming sensor readings
 - struct_message incomingmsg;
 - 
 - // Callback when data is sent
 - void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
 -   Serial.print("Last Packet Send Status: ");
 -   if (sendStatus == 0){
 -     Serial.println("Delivery success");
 -   }
 -   else{
 -     Serial.println("Delivery fail");
 -   }
 - }
 - 
 - // Callback when data is received
 - void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
 -   memcpy(&incomingmsg, incomingData, sizeof(outgoingmsg));
 -   Serial.print("Bytes received: ");
 -   Serial.println(len);
 - //store incoming data in variable
 -   IN_button_state = incomingmsg.button;
 -   if (IN_button_state==1){forward();}
 -   if (IN_button_state==2){backward();}
 -   if (IN_button_state==3){turnleft();}
 -   if (IN_button_state==4){turnright();}
 -   if (IN_button_state==5){nomotion();}
 -   
 -   
 - }
 - 
 - void getReadings(){
 -   // Read 
 -  OUT_button_state = analogRead(A0);
 - 
 -  delay(100);
 - //OUT 
 -   Serial.println("OUTGOING MESSAGES");
 -   
 -   Serial.println(OUT_button_state);
 -  }
 - 
 - void printIncomingMessage(){
 -   // Display Readings in Serial Monitor
 -   //IN
 -   Serial.println("INCOMING MESSAGES");
 -   
 -   Serial.println(IN_button_state);
 - 
 -   
 - }
 -  
 - void setup() {
 -  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); 
 -   pinMode(motor1a,OUTPUT);
 -     pinMode(motor1b,OUTPUT);
 -       pinMode(motor2a,OUTPUT);
 -         pinMode(motor2b,OUTPUT);
 -         pinMode(A0,INPUT);
 -   
 -   // Set device as a Wi-Fi Station
 -   WiFi.mode(WIFI_STA);
 -   WiFi.disconnect();
 - 
 -   // Init ESP-NOW
 -   if (esp_now_init() != 0) {
 -     Serial.println("Error initializing ESP-NOW");
 -     return;
 -   }
 - 
 -   // Set ESP-NOW Role
 -   esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
 - 
 -   // Once ESPNow is successfully Init, we will register for Send CB to
 -   // get the status of Trasnmitted packet
 -   esp_now_register_send_cb(OnDataSent);
 -   
 -   // Register peer
 -   esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_COMBO, 1, NULL, 0);
 -   
 -   // Register for a callback function that will be called when data is received
 -   esp_now_register_recv_cb(OnDataRecv);
 - }
 -  
 - void loop() {
 -  
 -     getReadings();
 -     
 - 
 -     //Set values to send
 -     outgoingmsg.button = OUT_button_state;
 -    
 - 
 -     // Send message via ESP-NOW
 -     esp_now_send(broadcastAddress, (uint8_t *) &outgoingmsg, sizeof(outgoingmsg));
 - 
 -     printIncomingMessage();
 -   }
 -   void forward()
 - {digitalWrite(motor1a,1);
 -  digitalWrite(motor2a,1);
 -  digitalWrite(motor1b,0);
 -  digitalWrite(motor2b,0);
 -  leds[0] = CRGB::Green;
 -  leds[1] = CRGB::Green;
 -   FastLED.show();
 -   delay(50);
 -   }
 -  void backward()
 - {digitalWrite(motor1a,0);
 -  digitalWrite(motor2a,0);
 -  digitalWrite(motor1b,1);
 -  digitalWrite(motor2b,1);
 -  leds[0] = CRGB::Red;
 -  leds[1] = CRGB::Red;
 -   FastLED.show();
 -   delay(50);
 -   }
 -  void turnleft()
 - {digitalWrite(motor1a,1);
 -  digitalWrite(motor2a,0);
 -  digitalWrite(motor1b,0);
 -  digitalWrite(motor2b,1);
 -  leds[0] = CRGB::Green;
 -   FastLED.show();
 -   delay(50);
 -   }
 -  void turnright()
 - {
 -   digitalWrite(motor1a,0);
 -  digitalWrite(motor2a,1);
 -  digitalWrite(motor1b,1);
 -  digitalWrite(motor2b,0);
 -  leds[1] = CRGB::Green;
 -   FastLED.show();
 -   delay(50);}
 -  void nomotion()
 - {digitalWrite(motor1a,0);
 -  digitalWrite(motor2a,0);
 -  digitalWrite(motor1b,0);
 -  digitalWrite(motor2b,0);}
 
  复制代码
  
 
 
 
发送端代码 
 
- #include <ESP8266WiFi.h>
 - #include <espnow.h>
 - #include <Wire.h>
 - #include <Adafruit_GFX.h>
 - #include <Adafruit_SSD1306.h>
 - #define SCREEN_WIDTH 128 // OLED display width, in pixels
 - #define SCREEN_HEIGHT 64 // OLED display height, in pixels
 - Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
 - uint8_t broadcastAddress[] = {0xAC, 0x0B, 0xFB, 0xCF, 0x16, 0x91};//SLAVE ESP8266 Board MAC Address: AC:0B:FB:CE:8B:16
 - 
 - 
 - String success;
 - #define upButton 2
 - #define downButton 14
 - #define leftButton 13
 - #define rightButton 12
 - 
 - typedef struct struct_message 
 - {
 - int button;
 - } 
 - struct_message;
 - int IN_button_state;
 - int OUT_button_state;
 - struct_message outgoingmsg;
 - struct_message incomingmsg;
 - 
 - // Callback when data is sent
 - void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
 -   Serial.print("Last Packet Send Status: ");
 -   if (sendStatus == 0){
 -     Serial.println("Delivery success");
 -   }
 -   else{
 -     Serial.println("Delivery fail");
 -   }
 - }
 - 
 - // Callback when data is received
 - void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
 -   memcpy(&incomingmsg, incomingData, sizeof(outgoingmsg));
 -   Serial.print("Bytes received: ");
 -   Serial.println(len);
 - //store incoming data in variable
 -   IN_button_state = incomingmsg.button;
 -   
 -  
 - }
 - 
 - void getReadings(){
 - 
 -  if((digitalRead(upButton)==0)&&(digitalRead(downButton)==1)&&(digitalRead(leftButton)==1)&&(digitalRead(rightButton)==1))
 - {
 -  OUT_button_state = 1;
 -  }
 -  if((digitalRead(upButton)==1)&&(digitalRead(downButton)==0)&&(digitalRead(leftButton)==1)&&(digitalRead(rightButton)==1))
 - {
 -  OUT_button_state = 2;
 -  }
 -  if((digitalRead(upButton)==1)&&(digitalRead(downButton)==1)&&(digitalRead(leftButton)==0)&&(digitalRead(rightButton)==1))
 - {
 -  OUT_button_state = 3;
 -  }
 -   if((digitalRead(upButton)==1)&&(digitalRead(downButton)==1)&&(digitalRead(leftButton)==1)&&(digitalRead(rightButton)==0))
 - {
 -  OUT_button_state = 4;
 -  }
 -   if((digitalRead(upButton)==1)&&(digitalRead(downButton)==1)&&(digitalRead(leftButton)==1)&&(digitalRead(rightButton)==1))
 - {
 -  OUT_button_state = 5;
 -  }
 - }
 -  
 - void setup() {
 -   
 -   Serial.begin(115200);
 -   pinMode(upButton,INPUT_PULLUP);
 -   pinMode(downButton,INPUT_PULLUP);
 -   pinMode(leftButton,INPUT_PULLUP);
 -   pinMode(rightButton,INPUT_PULLUP);
 -   if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
 -     Serial.println(F("SSD1306 allocation failed"));
 -     for(;;);
 -   }
 -   
 -   // Set device as a Wi-Fi Station
 -   WiFi.mode(WIFI_STA);
 -   WiFi.disconnect();
 - 
 -   // Init ESP-NOW
 -   if (esp_now_init() != 0) {
 -     Serial.println("Error initializing ESP-NOW");
 -     return;
 -   }
 - 
 -   // Set ESP-NOW Role
 -   esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
 - 
 -   // Once ESPNow is successfully Init, we will register for Send CB to
 -   // get the status of Trasnmitted packet
 -   esp_now_register_send_cb(OnDataSent);
 -   
 -   // Register peer
 -   esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_COMBO, 1, NULL, 0);
 -   
 -   // Register for a callback function that will be called when data is received
 -   esp_now_register_recv_cb(OnDataRecv);
 - }
 - void printIncomingMessage(){
 -   // Display Readings in Serial Monitor
 -   //IN
 -   Serial.println("INCOMING MESSAGES");
 -   
 -   Serial.println(IN_button_state);
 -   display.clearDisplay();
 -   display.setTextSize(2);
 -   display.setTextColor(WHITE);
 -   display.setCursor(10, 20);
 -   display.println("LIGHT: ");
 -   display.setCursor(80, 20);
 -   display.println(IN_button_state);
 -   display.display(); 
 -   delay(10);
 - 
 -   
 - }
 -  
 - void loop() {
 -   
 - 
 -     //Get DHT readings
 -     getReadings();
 - 
 -     //Set values to send
 -     outgoingmsg.button = OUT_button_state;
 -    
 - 
 -     // Send message via ESP-NOW
 -     esp_now_send(broadcastAddress, (uint8_t *) &outgoingmsg, sizeof(outgoingmsg));
 -     printIncomingMessage();
 - 
 - }
 
  复制代码
  
 
 
原文地址:https://www.hackster.io/e_s_c/3d-printeed-mars-rover-using-esp12e-03d609  
 
项目作者:edison science corner 
 
译文首发于:达尔闻说 
 
转载请注明来源信息 
 
 
 
 
 |