#include <dummy.h>
// =================================================================================================
// 电磁吸盘控制器
// 通过Modbus-rtu 控制占空比,占空比控制 电磁吸盘 的电流,进而控制电磁力
//
// =================================================================================================
// =================================================================================================
// eModbus: Copyright 2020 by Michael Harwerth, Bert Melis and the contributors to ModbusClient
// MIT license - see license.md for details
// =================================================================================================
#include <Arduino.h>
#include "HardwareSerial.h"
// Modbus server include
#include "ModbusServerRTU.h"
//增添宏定义 与RS485调制解调模块接口
#define RS485_RX_PIN 1
#define RS485_TX_PIN 0
#define RS485_ENABLE_PIN 18
#define RS485 Serial1
#define RS485_SerialNum UART_NUM_1
#define RTU_ADD 0x05
// 定义队列,用来传输数据
QueueHandle_t queueMsg = xQueueCreate(8, sizeof(char[2]));
////实现PWM控制
int duty_cycle_now = 0;
// use 8 bit precision for LEDC timer
#define LEDC_TIMER_8_BIT 8
const int MAX_DUTY_CYCLE = (int)(pow(2, LEDC_TIMER_8_BIT) - 1);
// use 1000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ 1000
// LED pins
// 这里实际连接的是电磁铁控制NPN
#define LED_PIN_1 8
//板载LED
#define LED_BUILTIN1 12
#define LED_BUILTIN2 13
//步进电机
// TB6600 定义控制引脚,共阴极接法。GPIO通过NPN(E接地)接TB6600控制角。
#define TB6600_EN 2
#define TB6600_DIR 3
#define TB6600_PUL 10
void pwmInit(){
pinMode(LED_PIN_1, OUTPUT);
pinMode(LED_BUILTIN1, OUTPUT);
pinMode(LED_BUILTIN2, OUTPUT);
digitalWrite(LED_BUILTIN1, LOW);
digitalWrite(LED_BUILTIN2, LOW);
// 配置PIN,频率,分辨率
ledcAttach(LED_PIN_1, LEDC_BASE_FREQ, LEDC_TIMER_8_BIT);
//// set the brightness on LEDC channel 0
pwmOut(0);
}
void pwmOut(int dutyCycle){
// 设置PWM波占空比, 值高,导通时间长,最大 MAX_DUTY_CYCLE,这里是255
if(dutyCycle <= MAX_DUTY_CYCLE)
{
// 按照新值输出PWM波信号
Serial.println("PWM_Duty:");
Serial.println(dutyCycle);
// set the brightness on LEDC channel 0
duty_cycle_now = MAX_DUTY_CYCLE-dutyCycle;
// write duty to LEDC
ledcWrite(LED_PIN_1, duty_cycle_now);
}
}
////定义PWM控制任务
//xTaskCreate(pwmTask, "pwmTask", 1024 * 8, NULL, 1, NULL);
void pwmTask(void *ptParam) { //LCD任务主体
pwmInit();
while (1) {
uint16_t PWM_Duty;
//TickType_t timeOut = portMAX_DELAY;
TickType_t timeOut = 10;
if (xQueueReceive(queueMsg, &PWM_Duty, timeOut) == pdPASS) {
pwmOut((int)PWM_Duty);
} else {
//Serial.println("Message Queue is Empty");
};
vTaskDelay(100);
}
}
// Modbus RTU 作为服务器 通信
// Create a ModbusRTU server instance listening with 2000ms timeout
ModbusServerRTU MBserver(2000); // 超时时长
// FC03: worker do serve Modbus function code 0x03 (READ_HOLD_REGISTER)
// 0x04 读取输入寄存器值 READ_INPUT_REGISTER
ModbusMessage FC04(ModbusMessage request) {
uint16_t address; // requested register address
uint16_t words; // requested number of registers
ModbusMessage response; // response message to be sent back
delay(100);
// get request values
request.get(2, address);
request.get(4, words);
// Serial.println(request.size());
// Serial.println("\n");
Serial.println("request:address and words");
Serial.println(address);
Serial.println(words);
// Address and words valid? We assume 10 registers here
if (address>=0 && words>=1 && (address + words) <= 10) {
// Looks okay. Set up message with serverID, FC and length of data
response.add(request.getServerID(), request.getFunctionCode(), (uint8_t)(words * 2));
// Fill response with requested data
for (uint16_t i = address; i < address + words; ++i) {
response.add((uint8_t)(duty_cycle_now>>8),(uint8_t)(duty_cycle_now%255));//当前PWM占空比
}
} else {
// No, either address or words are outside the limits. Set up error response.
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
}
return response;
}
// FC06: worker do serve Modbus function code 0x06 (READ_HOLD_REGISTER)
// 0x06 写单个保持寄存器
ModbusMessage FC06(ModbusMessage request) {
uint16_t address; // requested register address
uint16_t regvalue; // requested register value
ModbusMessage response; // response message to be sent back
delay(100);
// get request values
request.get(2, address);
request.get(4, regvalue);
Serial.println(regvalue);
// Address and words valid? We assume 10 registers here for demo
if ( (address== 0)&&(regvalue<=MAX_DUTY_CYCLE)) {
// Looks okay. Set up message with serverID, FC and length of data
response.add(request.getServerID(), request.getFunctionCode());
// Fill response with requested data
response.add((uint8_t)(regvalue>>8),(uint8_t)(regvalue%256));
// 数据发进队列
//portMAX_DELAY - 无限Block
//TickType_t timeOut = portMAX_DELAY;
TickType_t timeOut = 10;
if (xQueueSend(queueMsg, ®value, timeOut) != pdPASS) {
Serial.print("queue send error");
Serial.println("Queue is full.");
};
} else {
Serial.print("the MAX_DUTY_CYCLE is:");
Serial.println(MAX_DUTY_CYCLE);
// No, either address or words are outside the limits. Set up error response.
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
}
return response;
}
// Setup() - initialization happens here
void setup() {
// Init Serial monitor
Serial.begin(115200);
while (!Serial) {}
Serial.println("__ OK __");
// PWM初始化
pwmInit();
// RS485串口外设 连接 Modbus RTU
RTUutils::prepareHardwareSerial(RS485);
RS485.begin(115200, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN);
while (!RS485) {
delay(100);
Serial.println("__ oops! __");
}
// HS245 总线控制器芯片 导通
pinMode(RS485_ENABLE_PIN, OUTPUT);
digitalWrite(RS485_ENABLE_PIN, LOW);
if (!RS485.setMode(UART_MODE_RS485_HALF_DUPLEX)) {
Serial.print("Failed to set RS485 mode");
}
// END,RS485串口外设 连接 Modbus RTU
// Register served function code worker for server 1, FC 0x04
MBserver.registerWorker(RTU_ADD, READ_INPUT_REGISTER, &FC04);
MBserver.registerWorker(RTU_ADD, WRITE_HOLD_REGISTER, &FC06);
// Start ModbusRTU background task
MBserver.begin(RS485);
//启动PWM控制任务
xTaskCreate(pwmTask, "pwmTask", 1024 * 8, NULL, 3, NULL);
}
// loop() - nothing done here today!
void loop() {
digitalWrite(LED_BUILTIN1, LOW);
digitalWrite(LED_BUILTIN2, LOW);
delay(1000);
digitalWrite(LED_BUILTIN1, HIGH);
digitalWrite(LED_BUILTIN2, HIGH);
delay(1000);
// Serial.println("the main loop is running!");
//ledcWriteChannel(LEDC_CHANNEL, 250);
}