# arduino_Lan9252
本文作者:[WTB]
# *购买链接
# *B站视频链接
# arduino ethercat初识
arduino ethercat初识 (opens new window)
# arduino ethercat示例1-2详解
arduino ethercat示例1-2详解 (opens new window)
# arduino ethercat示例3-4详解
arduino ethercat示例3-4详解 (opens new window)
# arduino ethercat示例5-6详解
arduino ethercat示例5-6详解 (opens new window)
# arduino ethercat PWM闭环步进电机演示
arduino ethercat PWM闭环步进电机演示 (opens new window)
# *pythonsoem概述
本资料主要针对初识EthreCat的入门级的参考资料,内容主要分两大部分,一个是EtherCat的主站,主要以python开发语言为基础,一个是EtherCat从站,主要是以Uncleo-f303re和UNO结合Lan9252底板,环境为VSCode Arduino为主。
关键词:
1.EtherCat
2.设备 ID : 主设备识别的唯一ID
3.主站(master),从站(slave)
4.用于Arduino的ethercat库文件(easycat)
EasyNavigator : 主站通讯查看软件
EasyConfigurator :生产bin,xml,.h的配置软件
7.SOEM(Simple Open EtherCAT Master) : 本资资料用pysoem
8.LAN9252 : EtherCat的通讯芯片
9. PDO
10.SDO
11.SYNC MASTER
EtherCat通讯模式类型:
# *pysoem安装
pip install pysoem
# *示例1和2
example-01;
1.USB或者5V直流供电连接开发板,连接RJ_IN网口通过网线和电脑网口连接。
2.用EasyNavigator_GUI.exe软件搜索,确保能扫描到开发板从站。
3.用EasyCAT_Config_GUI.exe点击write EEPROM 烧写32_32_rev_1.bin。
4.程序中我们通过0.1秒增加计数来传入到PDO。
5.用EasyNavigator_GUI.exe软件可以直观的看到计数的增加。
6.在python中,使用pysoem将计数器值输出到终端。
example-02;
1.USB或者5V直流供电连接开发板,连接RJ_IN网口通过网线和电脑网口连接。
2.用EasyNavigator_GUI.exe软件搜索,确保能扫描到开发板从站。
3.打开Easy Configurator,直接创建自定义数据!
4.保存项目后点击create files,在保存项目的文件夹中会生成多个文件,将bin文件以write eeprom上传到lan9252,找到.h文件并将内容输入到Arduino!
基本步骤;
1.使用EasyConfigurator在LAN 9252上配置PDO ENTRY!
2.在Arduino上使用EasyCAT库,在INPUT PDO中输入间隔100毫秒的计数器值!
3.使用EasyNavigator验证PDO ENTRY在LAN 9252上配置是否正确!
4.在电脑上搜索网络助手!
5.使用pysoem连接到LAN 9252并切换到OP模式!
6.实时将PDO值输出到终端!
搜索网络适配器的python程序;
import pysoem
adapters = pysoem.find_adapters() for i, adapter in enumerate(adapters):
print('Adapter {}'.format(i))
print(' {}'.format(adapter.name))
print(' {}'.format(adapter.desc))
arduino示例1代码;
#include "EasyCAT.h"
#include <SPI.h>
EasyCAT EASYCAT(10);
unsigned long wtb_t = 0;
uint16_t wtb_cnt = 0;
void setup()
{
Serial.begin(9600);
Serial.print ("\nEasyCAT - Generic EtherCAT slave\n");
if (EASYCAT.Init() == true)
{
Serial.print ("initialized");
}
else
{
Serial.print ("initialization failed"); pinMode(13, OUTPUT);
while(1)
{
digitalWrite (13, LOW); delay(500);
digitalWrite (13, HIGH); delay(500);
}
}
}
void loop()
{
EASYCAT.MainTask(); Application();
}
void Application ()
{
if(millis() - wtb_t > 100){
wtb_t = millis();
wtb_cnt++;
EASYCAT.BufferIn.Byte[0] = wtb_cnt%256;
EASYCAT.BufferIn.Byte[1] = wtb_cnt/256;
}
}
Aduino示例2代码(自定义数据);
#define CUSTOM
#include "wtb.h"
#include "EasyCAT.h"
#include <SPI.h>
EasyCAT EASYCAT(10);
unsigned long wtb_t = 0;
uint16_t wtb_cnt = 0;
void setup()
{
Serial.begin(9600);
Serial.print ("\nEasyCAT - Generic EtherCAT slave\n"); if (EASYCAT.Init() == true)
{
Serial.print ("initialized");
}
else
{
Serial.print ("initialization failed"); pinMode(13, OUTPUT);
while(1)
{
digitalWrite (13, LOW); delay(500);
digitalWrite (13, HIGH); delay(500);
}
}
}
void loop()
{
EASYCAT.MainTask();
Application();
}
void Application ()
{
if(millis() - wtb_t > 100){
wtb_t = millis();
wtb_cnt++; //计数加1
//EASYCAT.BufferIn.Byte[0] = wtb_cnt%256;
//EASYCAT.BufferIn.Byte[1] = wtb_cnt/256;
EASYCAT.BufferIn.Cust.CNT = wtb_cnt;
}
}
arduino示例 2(wtb.h);
#ifndef CUSTOM_PDO_NAME_H
#define CUSTOM_PDO_NAME_H
#define CUST_BYTE_NUM_OUT 2
#define CUST_BYTE_NUM_IN 2
#define TOT_BYTE_NUM_ROUND_OUT 4
#define TOT_BYTE_NUM_ROUND_IN 4
typedef union //---- output buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_OUT]; struct
{
uint16_t DATA;
}Cust;
} PROCBUFFER_OUT;
ypedef union //---- input buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_IN]; struct
{
uint16_t CNT;
}Cust;
} PROCBUFFER_IN;
#endif
python主站代码:
import pysoem
import threading
import time
import ctypes
import struct
# EtherCAT
master = pysoem.Master()
master.open('\\Device\\NPF_{66641FB8-F1DA-40CB-995C-167AA57A21A0}')
if master.config_init() > 0:
print(f'共发现{len(master.slaves)}个从站')
else:
print('No slaves found')
master.close()
raise Exception("NO SLAVE")
slave = master.slaves[0]
master.config_map()
if master.state_check(pysoem.SAFEOP_STATE, timeout=50_000) != pysoem.SAFEOP_STATE:
master.close()
raise Exception("not all slaves reached SAFEOP state")
slave.dc_sync(act=True, sync0_cycle_time=10_000_000)
master.state = pysoem.OP_STATE
master.send_processdata()
master.receive_processdata(timeout=2000)
# request OP state for all slaves
master.write_state()
all_slaves_reached_op_state = False
for i in range(40):
master.state_check(pysoem.OP_STATE, timeout=50_000)
if master.state == pysoem.OP_STATE:
all_slaves_reached_op_state = True
break
if all_slaves_reached_op_state:
print("OP_MODULE")
def thread1():
while True:
master.send_processdata()
master.receive_processdata(timeout=2000)
cnt1 = int.from_bytes(slave.input[0:2], byteorder='little', signed=False)
cnt2 = slave.input[1] * 256 + slave.input[0]
print(f"cnt1={cnt1}, cnt2={cnt2}")
#print(f"cnt1={cnt1}")
time.sleep(0.5)
ethercat_thread = threading.Thread(target=thread1, daemon=True)
ethercat_thread.start()
# 中断处理
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
print("中断.")
master.state = pysoem.INIT_STATE
# request INIT state for all slaves
master.write_state()
master.close()
# *示例3和4
主要内容: 1.将上一篇中进行的教程示例升级到具有GUI的python程序! 2.将可变电阻连接到阿杜伊诺的模拟0号插针上,并将测量出的10bit模拟值以无符号的16bit整数输入input pdo,发送到主节点! 3.示例3中获取开发板拨码开关的值,当值在0-255之间来回 切换时,请在input pdo中输入值并发送! 4.示例4将温湿度传感器(DHT-11)连接到阿杜伊诺的数字2号插针上,并将测量的温湿度值输出到python gui主屏幕
arduino示例3和4:
#include "main.h"
#include "EasyCAT.h" // EasyCAT library to interface the LAN9252
#include "DHT.h"
#include <Arduino.h>
#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \
defined(STM32WB) || defined(STM32MP1) || defined(STM32L5) )
#error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting.
#endif
// These define's must be placed at the beginning before #include "STM32TimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system.
#define TIMER_INTERRUPT_DEBUG 0
#define _TIMERINTERRUPT_LOGLEVEL_ 0
#include "STM32TimerInterrupt.h"
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "STM32_ISR_Timer.h"
#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
#define TIMER_INTERVAL_MS 100
#define HW_TIMER_INTERVAL_MS 50
#ifndef LED_BUILTIN
#define LED_BUILTIN PC13 // Pin 33/PB0 control on-board LED_GREEN on F767ZI
#endif
// Depending on the board, you can select STM32 Hardware Timer from TIM1-TIM22
// For example, F767ZI can select Timer from TIM1-TIM14
// If you select a Timer not correctly, you'll get a message from ci[ompiler
// 'TIMxx' was not declared in this scope; did you mean 'TIMyy'?
// Init STM32 timer TIM1
STM32Timer ITimer(TIM1);
HardwareSerial Serial1(PA10,PA9);
// Init STM32_ISR_Timer
// Each STM32_ISR_Timer can service 16 different ISR-based timers
STM32_ISR_Timer ISR_Timer;
#define TIMER_INTERVAL_0_5S 500L
#define TIMER_INTERVAL_1S 1000L
#define TIMER_INTERVAL_1_5S 1500L
#define TIMER_INTERVAL_5S 5000L
void TimerHandler()
{
ISR_Timer.run();
}
unsigned long previousMs = 0;
uint16_t wtbcnt = 0;
const int OUTPUTS_COUNT = 8;
const char DHTPIN = PIN_A0;
const char DHTTYPE = DHT11;
// const int outPins[8] = {
// BitOut0, BitOut1, BitOut2, BitOut3, BitOut4, BitOut5, BitOut6, BitOut7
// };
// const int InPins[8] = {
// BitIn0, BitIn1, BitIn2, BitIn3, BitIn4, BitIn5, BitIn6, BitIn7
// };
//---- setup ---------------------------------------------------------------------------------------
uint8_t humid;
uint8_t temp;
DHT dht(DHTPIN, DHTTYPE);
void adapte_DHT()
{
digitalWrite(BitOut0, !digitalRead(BitOut0));
humid = dht.readHumidity();
temp = dht.readTemperature();
//float hic = dht.computeHeatIndex(t, h, false);
// Serial1.print(F("Humidity: "));
// Serial1.print(h);
// Serial1.print(F("% Temperature: "));
// Serial1.print(t);
// Serial1.print(F("掳C "));
// Serial1.print(hic);
// Serial1.print(F("掳C "));
}
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
Serial1.print("Initialization...");
dht.begin();
pinMode(BitOut0,HIGH);
// pinMode(BitOut1,HIGH);
// pinMode(BitOut2,HIGH);
// pinMode(BitOut3,HIGH);
// pinMode(BitOut4,HIGH);
// pinMode(BitOut5,HIGH);
// pinMode(BitOut6,HIGH);
// pinMode(BitOut7,HIGH);
// digitalWrite (BitOut0, HIGH);
// digitalWrite (BitOut1, HIGH);
// digitalWrite (BitOut2, HIGH);
// digitalWrite (BitOut3, HIGH);
// digitalWrite (BitOut4, HIGH);
// digitalWrite (BitOut5, HIGH);
// digitalWrite (BitOut6, HIGH);
// digitalWrite (BitOut7, HIGH);
pinMode(BitIn0, INPUT_PULLUP);
pinMode(BitIn1, INPUT_PULLUP);
pinMode(BitIn2, INPUT_PULLUP);
pinMode(BitIn3, INPUT_PULLUP);
pinMode(BitIn4, INPUT_PULLUP);
pinMode(BitIn5, INPUT_PULLUP);
pinMode(BitIn6, INPUT_PULLUP);
pinMode(BitIn7, INPUT_PULLUP);
// for (size_t i = 0; i < OUTPUTS_COUNT; i++)
// {
// int outPin = outPins[i];
// pinMode(outPin, OUTPUT);
// }
if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler))
{
Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(millis());
}
else
Serial.println(F("Can't set ITimer. Select another freq. or timer"));
ISR_Timer.setInterval(TIMER_INTERVAL_0_5S, adapte_DHT);
if (EasyCAT_Init(SpiCS_Pin, ASYNC) == true) {
Serial.println("done.");
}
else
{
// initialization failed, blink LED until reset
Serial.println("failed!");
pinMode(BitOut0, OUTPUT);
while(1)
{
digitalWrite (BitOut0, LOW);
delay(500);
digitalWrite (BitOut0, HIGH);
delay(500);
}
}
previousMs = millis();
}
//---- main loop ----------------------------------------------------------------------------------------
void loop()
{
EasyCAT_MainTask();
Application();
}
//---- user application ------------------------------------------------------------------------------
void Application ()
{
// #define ECAT_APP_CYCLE_TIME_MS 100
// unsigned long nowMs = millis();
// if (nowMs - previousMs >= ECAT_APP_CYCLE_TIME_MS)
// {
// previousMs = nowMs;
// //wtbcnt++;
// EasyCAT_BufferIn.Cust.CNT = 80;
// // EasyCAT_BufferIn.Cust.CNT = wtbcnt;
// // read slave RxPDO
// // for (size_t i = 0; i < OUTPUTS_COUNT; i++)
// // {
// // int outPin = outPins[i];
// // if (EasyCAT_BufferOut.Cust.Out8 & (1 << i)) {
// // digitalWrite (outPin, LOW);
// // }
// // else {
// // digitalWrite (outPin, HIGH);
// // }
// // }
// }
EasyCAT_BufferIn.Cust.CNT = humid;
// if (digitalRead(BitIn0)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<0); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<0);
// if (digitalRead(BitIn1)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<1); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<1);
// if (digitalRead(BitIn2)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<2); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<2);
// if (digitalRead(BitIn3)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<3); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<3);
// if (digitalRead(BitIn4)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<4); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<4);
// if (digitalRead(BitIn5)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<5); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<5);
// if (digitalRead(BitIn6)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<6); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<6);
// if (digitalRead(BitIn7)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<7); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<7);
}
示例3和4的 wth_01.h
#ifndef CUSTOM_PDO_NAME_H
#define CUSTOM_PDO_NAME_H
//-------------------------------------------------------------------//
// //
// This file has been created by the Easy Configurator tool //
// //
// Easy Configurator project ex01.prj
// //
//-------------------------------------------------------------------//
#define CUST_BYTE_NUM_OUT 2
#define CUST_BYTE_NUM_IN 2
#define TOT_BYTE_NUM_ROUND_OUT 4
#define TOT_BYTE_NUM_ROUND_IN 4
typedef union //---- output buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_OUT];
struct
{
uint16_t DATA;
}Cust;
} PROCBUFFER_OUT;
typedef union //---- input buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_IN];
struct
{
uint16_t CNT;
}Cust;
} PROCBUFFER_IN;
#endif
示例3和4的python GUI代码:
import pysoem
import threading
import time
import ctypes
import struct
import tkinter as tk
from tkinter import messagebox
master = pysoem.Master()
master.open('\\Device\\NPF_{66641FB8-F1DA-40CB-995C-167AA57A21A0}')
if master.config_init() > 0:
print(f'共发现{len(master.slaves)}个从站')
else:
print('No slaves found')
master.close()
raise Exception("NO SLAVE")
slave = master.slaves[0]
master.config_map()
if master.state_check(pysoem.SAFEOP_STATE, timeout=50_000) != pysoem.SAFEOP_STATE:
master.close()
raise Exception("not all slaves reached SAFEOP state")
slave.dc_sync(act=True, sync0_cycle_time=10_000_000)
master.state = pysoem.OP_STATE
master.send_processdata()
master.receive_processdata(timeout=2000)
master.write_state()
all_slaves_reached_op_state = False
for i in range(40):
master.state_check(pysoem.OP_STATE, timeout=50_000)
if master.state == pysoem.OP_STATE:
all_slaves_reached_op_state = True
break
if all_slaves_reached_op_state:
print("OP_MODULE")
# GUI
root = tk.Tk()
root.title("ethercat的通讯程序")
root.geometry("600x400")
label1 = tk.Label(root, text="湿度 值=0", font=("Arial", 30))
label1.pack()
def thread1():
while True:
master.send_processdata()
master.receive_processdata(timeout=2000)
cnt1 = int.from_bytes(slave.input[0:2], byteorder='little', signed=False)
#print(f"cnt1={cnt1}")
label1.config(text=f"湿度 值={cnt1}")
time.sleep(0.1)
ethercat_thread = threading.Thread(target=thread1, daemon=True)
ethercat_thread.start()
root.mainloop()
print("程序已关闭.")
master.state = pysoem.INIT_STATE
# request INIT state for all slaves master.write_state()
master.close()
# *示例5和6
主要内容:
补充示例4温湿度的示例,示例6,led的输出控制。
arduino示例5:
#include "main.h"
#include "EasyCAT.h" // EasyCAT library to interface the LAN9252
#include "DHT.h"
#include <Arduino.h>
#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \
defined(STM32WB) || defined(STM32MP1) || defined(STM32L5) )
#error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting.
#endif
// These define's must be placed at the beginning before #include "STM32TimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system.
#define TIMER_INTERRUPT_DEBUG 0
#define _TIMERINTERRUPT_LOGLEVEL_ 0
#include "STM32TimerInterrupt.h"
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "STM32_ISR_Timer.h"
#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
#define TIMER_INTERVAL_MS 100
#define HW_TIMER_INTERVAL_MS 50
#ifndef LED_BUILTIN
#define LED_BUILTIN PC13 // Pin 33/PB0 control on-board LED_GREEN on F767ZI
#endif
// Depending on the board, you can select STM32 Hardware Timer from TIM1-TIM22
// For example, F767ZI can select Timer from TIM1-TIM14
// If you select a Timer not correctly, you'll get a message from ci[ompiler
// 'TIMxx' was not declared in this scope; did you mean 'TIMyy'?
// Init STM32 timer TIM1
STM32Timer ITimer(TIM1);
HardwareSerial Serial1(PA10,PA9);
// Init STM32_ISR_Timer
// Each STM32_ISR_Timer can service 16 different ISR-based timers
STM32_ISR_Timer ISR_Timer;
#define TIMER_INTERVAL_0_5S 500L
#define TIMER_INTERVAL_1S 1000L
#define TIMER_INTERVAL_1_5S 1500L
#define TIMER_INTERVAL_5S 5000L
void TimerHandler()
{
ISR_Timer.run();
}
unsigned long previousMs = 0;
uint16_t wtbcnt = 0;
const int OUTPUTS_COUNT = 8;
const char DHTPIN = PIN_A0;
const char DHTTYPE = DHT11;
// const int outPins[8] = {
// BitOut0, BitOut1, BitOut2, BitOut3, BitOut4, BitOut5, BitOut6, BitOut7
// };
// const int InPins[8] = {
// BitIn0, BitIn1, BitIn2, BitIn3, BitIn4, BitIn5, BitIn6, BitIn7
// };
//---- setup ---------------------------------------------------------------------------------------
float humid;
float temp;
DHT dht(DHTPIN, DHTTYPE);
union{
int16_t num1; //16bit
byte num2[2]; //16bit
}wtb1;
union{
uint16_t num1; //16bit
byte num2[2]; //16bit
}wtb2;
void adapte_DHT()
{
digitalWrite(BitOut0, !digitalRead(BitOut0));
humid = dht.readHumidity();
temp = dht.readTemperature();
wtb1.num1 = (int16_t)(temp*10);
wtb2.num1 = (uint16_t)(humid*10);
//float hic = dht.computeHeatIndex(t, h, false);
// Serial1.print(F("Humidity: "));
// Serial1.print(h);
// Serial1.print(F("% Temperature: "));
// Serial1.print(t);
// Serial1.print(F("掳C "));
// Serial1.print(hic);
// Serial1.print(F("掳C "));
}
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
Serial1.print("Initialization...");
dht.begin();
pinMode(BitOut0,HIGH);
// pinMode(BitOut1,HIGH);
// pinMode(BitOut2,HIGH);
// pinMode(BitOut3,HIGH);
// pinMode(BitOut4,HIGH);
// pinMode(BitOut5,HIGH);
// pinMode(BitOut6,HIGH);
// pinMode(BitOut7,HIGH);
// digitalWrite (BitOut0, HIGH);
// digitalWrite (BitOut1, HIGH);
// digitalWrite (BitOut2, HIGH);
// digitalWrite (BitOut3, HIGH);
// digitalWrite (BitOut4, HIGH);
// digitalWrite (BitOut5, HIGH);
// digitalWrite (BitOut6, HIGH);
// digitalWrite (BitOut7, HIGH);
pinMode(BitIn0, INPUT_PULLUP);
pinMode(BitIn1, INPUT_PULLUP);
pinMode(BitIn2, INPUT_PULLUP);
pinMode(BitIn3, INPUT_PULLUP);
pinMode(BitIn4, INPUT_PULLUP);
pinMode(BitIn5, INPUT_PULLUP);
pinMode(BitIn6, INPUT_PULLUP);
pinMode(BitIn7, INPUT_PULLUP);
// for (size_t i = 0; i < OUTPUTS_COUNT; i++)
// {
// int outPin = outPins[i];
// pinMode(outPin, OUTPUT);
// }
if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler))
{
Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(millis());
}
else
Serial.println(F("Can't set ITimer. Select another freq. or timer"));
ISR_Timer.setInterval(TIMER_INTERVAL_0_5S, adapte_DHT);
if (EasyCAT_Init(SpiCS_Pin, ASYNC) == true) {
Serial.println("done.");
}
else
{
// initialization failed, blink LED until reset
Serial.println("failed!");
pinMode(BitOut0, OUTPUT);
while(1)
{
digitalWrite (BitOut0, LOW);
delay(500);
digitalWrite (BitOut0, HIGH);
delay(500);
}
}
previousMs = millis();
}
//---- main loop ----------------------------------------------------------------------------------------
void loop()
{
EasyCAT_MainTask();
Application();
}
//---- user application ------------------------------------------------------------------------------
void Application ()
{
// #define ECAT_APP_CYCLE_TIME_MS 100
// unsigned long nowMs = millis();
// if (nowMs - previousMs >= ECAT_APP_CYCLE_TIME_MS)
// {
// previousMs = nowMs;
// //wtbcnt++;
// EasyCAT_BufferIn.Cust.CNT = 80;
// // EasyCAT_BufferIn.Cust.CNT = wtbcnt;
// // read slave RxPDO
// // for (size_t i = 0; i < OUTPUTS_COUNT; i++)
// // {
// // int outPin = outPins[i];
// // if (EasyCAT_BufferOut.Cust.Out8 & (1 << i)) {
// // digitalWrite (outPin, LOW);
// // }
// // else {
// // digitalWrite (outPin, HIGH);
// // }
// // }
// }
EasyCAT_BufferIn.Byte[0] = wtb1.num2[0];
EasyCAT_BufferIn.Byte[1] = wtb1.num2[1];
EasyCAT_BufferIn.Byte[2] = wtb2.num2[0];
EasyCAT_BufferIn.Byte[3] = wtb2.num2[1];
// if (digitalRead(BitIn0)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<0); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<0);
// if (digitalRead(BitIn1)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<1); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<1);
// if (digitalRead(BitIn2)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<2); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<2);
// if (digitalRead(BitIn3)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<3); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<3);
// if (digitalRead(BitIn4)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<4); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<4);
// if (digitalRead(BitIn5)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<5); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<5);
// if (digitalRead(BitIn6)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<6); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<6);
// if (digitalRead(BitIn7)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<7); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<7);
}
示例5的wtb_05.h
#ifndef CUSTOM_PDO_NAME_H
#define CUSTOM_PDO_NAME_H
//-------------------------------------------------------------------//
// //
// This file has been created by the Easy Configurator tool //
// //
// Easy Configurator project wtb_05.prj
// //
//-------------------------------------------------------------------//
#define CUST_BYTE_NUM_OUT 2
#define CUST_BYTE_NUM_IN 4
#define TOT_BYTE_NUM_ROUND_OUT 4
#define TOT_BYTE_NUM_ROUND_IN 4
typedef union //---- output buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_OUT];
struct
{
uint16_t DATA;
}Cust;
} PROCBUFFER_OUT;
typedef union //---- input buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_IN];
struct
{
uint32_t CNT;
}Cust;
} PROCBUFFER_IN;
#endif
示例5的python GUI
import pysoem
import threading
import time
import ctypes
import struct
import tkinter as tk
from tkinter import messagebox
master = pysoem.Master()
master.open('\\Device\\NPF_{66641FB8-F1DA-40CB-995C-167AA57A21A0}')
if master.config_init() > 0:
print(f'共发现{len(master.slaves)}个从站')
else:
print('No slaves found')
master.close()
raise Exception("NO SLAVE")
slave = master.slaves[0]
master.config_map()
if master.state_check(pysoem.SAFEOP_STATE, timeout=50_000) != pysoem.SAFEOP_STATE:
master.close()
raise Exception("not all slaves reached SAFEOP state")
slave.dc_sync(act=True, sync0_cycle_time=10_000_000)
master.state = pysoem.OP_STATE
master.send_processdata()
master.receive_processdata(timeout=2000)
master.write_state()
all_slaves_reached_op_state = False
for i in range(40):
master.state_check(pysoem.OP_STATE, timeout=50_000)
if master.state == pysoem.OP_STATE:
all_slaves_reached_op_state = True
break
if all_slaves_reached_op_state:
print("OP_MODULE")
# GUI
root = tk.Tk()
root.title("ethercat的通讯程序")
root.geometry("600x400")
label1 = tk.Label(root, text="温度 值=0", font=("Arial", 30))
label1.pack()
label2 = tk.Label(root, text="湿度 值=0", font=("Arial", 30))
label2.pack()
def thread1():
while True:
master.send_processdata()
master.receive_processdata(timeout=2000)
cnt1 = int.from_bytes(slave.input[0:2], byteorder='little', signed=True)
cnt2 = int.from_bytes(slave.input[2:4], byteorder='little', signed=False)
#print(f"cnt1={cnt1}")
label1.config(text=f"温度 值={cnt1/10}°C")
label2.config(text=f"湿度 值={cnt2/10}%")
time.sleep(0.1)
ethercat_thread = threading.Thread(target=thread1, daemon=True)
ethercat_thread.start()
root.mainloop()
print("程序已关闭.")
master.state = pysoem.INIT_STATE
# request INIT state for all slaves master.write_state()
master.close()
arduino示例6代码-PDO-LED控制
#include "main.h"
#include "EasyCAT.h" // EasyCAT library to interface the LAN9252
#include "DHT.h"
#include <Arduino.h>
#if !( defined(STM32F0) || defined(STM32F1) || defined(STM32F2) || defined(STM32F3) ||defined(STM32F4) || defined(STM32F7) || \
defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32H7) ||defined(STM32G0) || defined(STM32G4) || \
defined(STM32WB) || defined(STM32MP1) || defined(STM32L5) )
#error This code is designed to run on STM32F/L/H/G/WB/MP1 platform! Please check your Tools->Board setting.
#endif
// These define's must be placed at the beginning before #include "STM32TimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system.
#define TIMER_INTERRUPT_DEBUG 0
#define _TIMERINTERRUPT_LOGLEVEL_ 0
#include "STM32TimerInterrupt.h"
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "STM32_ISR_Timer.h"
#include <SimpleTimer.h> // https://github.com/jfturcot/SimpleTimer
#define TIMER_INTERVAL_MS 100
#define HW_TIMER_INTERVAL_MS 50
#ifndef LED_BUILTIN
#define LED_BUILTIN PC13 // Pin 33/PB0 control on-board LED_GREEN on F767ZI
#endif
// Depending on the board, you can select STM32 Hardware Timer from TIM1-TIM22
// For example, F767ZI can select Timer from TIM1-TIM14
// If you select a Timer not correctly, you'll get a message from ci[ompiler
// 'TIMxx' was not declared in this scope; did you mean 'TIMyy'?
// Init STM32 timer TIM1
STM32Timer ITimer(TIM1);
HardwareSerial Serial1(PA10,PA9);
// Init STM32_ISR_Timer
// Each STM32_ISR_Timer can service 16 different ISR-based timers
STM32_ISR_Timer ISR_Timer;
#define TIMER_INTERVAL_0_5S 500L
#define TIMER_INTERVAL_1S 1000L
#define TIMER_INTERVAL_1_5S 1500L
#define TIMER_INTERVAL_5S 5000L
void TimerHandler()
{
ISR_Timer.run();
}
unsigned long previousMs = 0;
uint16_t wtbcnt = 0;
const int OUTPUTS_COUNT = 8;
const char DHTPIN = PIN_A0;
const char DHTTYPE = DHT11;
const int outPins[8] = {
BitOut0, BitOut1, BitOut2, BitOut3, BitOut4, BitOut5, BitOut6, BitOut7
};
// const int InPins[8] = {
// BitIn0, BitIn1, BitIn2, BitIn3, BitIn4, BitIn5, BitIn6, BitIn7
// };
//---- setup ---------------------------------------------------------------------------------------
float humid;
float temp;
DHT dht(DHTPIN, DHTTYPE);
union{
int16_t num1; //16bit
byte num2[2]; //16bit
}wtb1;
union{
uint16_t num1; //16bit
byte num2[2]; //16bit
}wtb2;
void adapte_DHT()
{
// digitalWrite(BitOut0, !digitalRead(BitOut0));
humid = dht.readHumidity();
temp = dht.readTemperature();
wtb1.num1 = (int16_t)(temp*10);
wtb2.num1 = (uint16_t)(humid*10);
//float hic = dht.computeHeatIndex(t, h, false);
// Serial1.print(F("Humidity: "));
// Serial1.print(h);
// Serial1.print(F("% Temperature: "));
// Serial1.print(t);
// Serial1.print(F("掳C "));
// Serial1.print(hic);
// Serial1.print(F("掳C "));
}
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
Serial1.print("Initialization...");
dht.begin();
pinMode(BitOut0,HIGH);
pinMode(BitOut1,HIGH);
pinMode(BitOut2,HIGH);
pinMode(BitOut3,HIGH);
pinMode(BitOut4,HIGH);
pinMode(BitOut5,HIGH);
pinMode(BitOut6,HIGH);
pinMode(BitOut7,HIGH);
// digitalWrite (BitOut0, HIGH);
// digitalWrite (BitOut1, HIGH);
// digitalWrite (BitOut2, HIGH);
// digitalWrite (BitOut3, HIGH);
// digitalWrite (BitOut4, HIGH);
// digitalWrite (BitOut5, HIGH);
// digitalWrite (BitOut6, HIGH);
// digitalWrite (BitOut7, HIGH);
pinMode(BitIn0, INPUT_PULLUP);
pinMode(BitIn1, INPUT_PULLUP);
pinMode(BitIn2, INPUT_PULLUP);
pinMode(BitIn3, INPUT_PULLUP);
pinMode(BitIn4, INPUT_PULLUP);
pinMode(BitIn5, INPUT_PULLUP);
pinMode(BitIn6, INPUT_PULLUP);
pinMode(BitIn7, INPUT_PULLUP);
// for (size_t i = 0; i < OUTPUTS_COUNT; i++)
// {
// int outPin = outPins[i];
// // pinMode(outPin, OUTPUT);
// digitalWrite(outPin,LOW);
// }
if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler))
{
Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(millis());
}
else
Serial.println(F("Can't set ITimer. Select another freq. or timer"));
ISR_Timer.setInterval(TIMER_INTERVAL_0_5S, adapte_DHT);
if (EasyCAT_Init(SpiCS_Pin, ASYNC) == true) {
Serial.println("done.");
}
else
{
// initialization failed, blink LED until reset
Serial.println("failed!");
pinMode(BitOut0, OUTPUT);
while(1)
{
digitalWrite (BitOut0, LOW);
delay(500);
digitalWrite (BitOut0, HIGH);
delay(500);
}
}
previousMs = millis();
}
//---- main loop ----------------------------------------------------------------------------------------
void loop()
{
EasyCAT_MainTask();
Application();
}
//---- user application ------------------------------------------------------------------------------
void Application ()
{
#define ECAT_APP_CYCLE_TIME_MS 100
unsigned long nowMs = millis();
if (nowMs - previousMs >= ECAT_APP_CYCLE_TIME_MS)
{
previousMs = nowMs;
//wtbcnt++;
//EasyCAT_BufferIn.Cust.CNT = 80;
// EasyCAT_BufferIn.Cust.CNT = wtbcnt;
// read slave RxPDO
// for (size_t i = 0; i < OUTPUTS_COUNT; i++)
// {
// int outPin = outPins[i];
// if (EasyCAT_BufferOut.Cust.DATA & (1 << i)) {
// digitalWrite (outPin, LOW);
// }
// else {
// digitalWrite (outPin, HIGH);
// }
// }
if (EasyCAT_BufferOut.Byte[0] & (1 << 0)) {
digitalWrite (BitOut0, LOW);
}
else {
digitalWrite (BitOut0, HIGH);
}
if (EasyCAT_BufferOut.Byte[1] & (1 << 0)) {
digitalWrite (BitOut1, LOW);
}
else {
digitalWrite (BitOut1, HIGH);
}
if (EasyCAT_BufferOut.Byte[2] & (1 << 0)) {
digitalWrite (BitOut2, LOW);
}
else {
digitalWrite (BitOut2, HIGH);
}
if (EasyCAT_BufferOut.Byte[3] & (1 << 0)) {
digitalWrite (BitOut3, LOW);
}
else {
digitalWrite (BitOut3, HIGH);
}
if (EasyCAT_BufferOut.Byte[4] & (1 << 0)) {
digitalWrite (BitOut4, LOW);
}
else {
digitalWrite (BitOut4, HIGH);
}
if (EasyCAT_BufferOut.Byte[5] & (1 << 0)) {
digitalWrite (BitOut5, LOW);
}
else {
digitalWrite (BitOut5, HIGH);
}
if (EasyCAT_BufferOut.Byte[6] & (1 << 0)) {
digitalWrite (BitOut6, LOW);
}
else {
digitalWrite (BitOut6, HIGH);
}
if (EasyCAT_BufferOut.Byte[7] & (1 << 0)) {
digitalWrite (BitOut7, LOW);
}
else {
digitalWrite (BitOut7, HIGH);
}
// digitalWrite(BitOut0,!EasyCAT_BufferOut.Byte[0]);
// digitalWrite(BitOut1,!EasyCAT_BufferOut.Byte[1]);
// digitalWrite(BitOut2,!EasyCAT_BufferOut.Byte[2]);
// digitalWrite(BitOut3,!EasyCAT_BufferOut.Byte[3]);
// digitalWrite(BitOut4,!EasyCAT_BufferOut.Byte[4]);
// digitalWrite(BitOut5,!EasyCAT_BufferOut.Byte[5]);
// digitalWrite(BitOut6,!EasyCAT_BufferOut.Byte[6]);
// digitalWrite(BitOut7,!EasyCAT_BufferOut.Byte[7]);
EasyCAT_BufferIn.Byte[0] = wtb1.num2[0];
EasyCAT_BufferIn.Byte[1] = wtb1.num2[1];
EasyCAT_BufferIn.Byte[2] = wtb2.num2[0];
EasyCAT_BufferIn.Byte[3] = wtb2.num2[1];
}
// EasyCAT_BufferIn.Byte[0] = wtb1.num2[0];
// EasyCAT_BufferIn.Byte[1] = wtb1.num2[1];
// EasyCAT_BufferIn.Byte[2] = wtb2.num2[0];
// EasyCAT_BufferIn.Byte[3] = wtb2.num2[1];
// if (digitalRead(BitIn0)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<0); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<0);
// if (digitalRead(BitIn1)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<1); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<1);
// if (digitalRead(BitIn2)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<2); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<2);
// if (digitalRead(BitIn3)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<3); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<3);
// if (digitalRead(BitIn4)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<4); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<4);
// if (digitalRead(BitIn5)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<5); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<5);
// if (digitalRead(BitIn6)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<6); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<6);
// if (digitalRead(BitIn7)) // the four input pins are mapped to the
// EasyCAT_BufferIn.Cust.CNT &= ~(1<<7); // lower nibble of input Byte 6
// else //
// EasyCAT_BufferIn.Cust.CNT |= (1<<7);
}
示例6的wtb_05.h
#ifndef CUSTOM_PDO_NAME_H
#define CUSTOM_PDO_NAME_H
//-------------------------------------------------------------------//
// //
// This file has been created by the Easy Configurator tool //
// //
// Easy Configurator project wtb_05.prj
// //
//-------------------------------------------------------------------//
#define CUST_BYTE_NUM_OUT 8
#define CUST_BYTE_NUM_IN 4
#define TOT_BYTE_NUM_ROUND_OUT 8
#define TOT_BYTE_NUM_ROUND_IN 4
typedef union //---- output buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_OUT];
struct
{
uint64_t DATA;
}Cust;
} PROCBUFFER_OUT;
typedef union //---- input buffer ----
{
uint8_t Byte [TOT_BYTE_NUM_ROUND_IN];
struct
{
uint32_t CNT;
}Cust;
} PROCBUFFER_IN;
#endif
示例6 python GUI代码
import pysoem
import threading
import time
import ctypes
import struct
import tkinter as tk
from tkinter import messagebox
master = pysoem.Master()
master.open('\\Device\\NPF_{66641FB8-F1DA-40CB-995C-167AA57A21A0}')
if master.config_init() > 0:
print(f'共发现{len(master.slaves)}个从站')
else:
print('No slaves found')
master.close()
raise Exception("NO SLAVE")
slave = master.slaves[0]
master.config_map()
if master.state_check(pysoem.SAFEOP_STATE, timeout=50_000) != pysoem.SAFEOP_STATE:
master.close()
raise Exception("not all slaves reached SAFEOP state")
slave.dc_sync(act=True, sync0_cycle_time=10_000_000)
master.state = pysoem.OP_STATE
master.send_processdata()
master.receive_processdata(timeout=2000)
master.write_state()
all_slaves_reached_op_state = False
for i in range(40):
master.state_check(pysoem.OP_STATE, timeout=50_000)
if master.state == pysoem.OP_STATE:
all_slaves_reached_op_state = True
break
if all_slaves_reached_op_state:
print("OP_MODULE")
output_len = len(slave.output)
#output_len = 7
print(f"output_len={output_len}")
tmp = bytearray([0 for i in range(output_len)])
def led_control(num,state):
print(f"LED={num},STATE={state}")
tmp[num] = state
slave.output = bytes(tmp)
master.send_processdata()
# GUI
root = tk.Tk()
root.title("ethercat的通讯程序")
root.geometry("600x400")
label1 = tk.Label(root, text="温度 值=0", font=("Arial", 30))
label1.pack()
label2 = tk.Label(root, text="湿度 值=0", font=("Arial", 30))
label2.pack()
btn_led1_on = tk.Button(root, text="LED1 ON",command=lambda:led_control(0,1))
btn_led1_on.pack()
btn_led1_off = tk.Button(root, text="LED1 OFF",command=lambda:led_control(0,0))
btn_led1_off.pack()
btn_led2_on = tk.Button(root, text="LED2 ON",command=lambda:led_control(1,1))
btn_led2_on.pack()
btn_led2_off = tk.Button(root, text="LED2 OFF",command=lambda:led_control(1,0))
btn_led2_off.pack()
btn_led3_on = tk.Button(root, text="LED3 ON",command=lambda:led_control(2,1))
btn_led3_on.pack()
btn_led3_off = tk.Button(root, text="LED3 OFF",command=lambda:led_control(2,0))
btn_led3_off.pack()
btn_led4_on = tk.Button(root, text="LED4 ON",command=lambda:led_control(3,1))
btn_led4_on.pack()
btn_led4_off = tk.Button(root, text="LED4 OFF",command=lambda:led_control(3,0))
btn_led4_off.pack()
btn_led5_on = tk.Button(root, text="LED5 ON",command=lambda:led_control(4,1))
btn_led5_on.pack()
btn_led5_off = tk.Button(root, text="LED5 OFF",command=lambda:led_control(4,0))
btn_led5_off.pack()
def thread1():
while True:
master.send_processdata()
master.receive_processdata(timeout=2000)
cnt1 = int.from_bytes(slave.input[0:2], byteorder='little', signed=True)
cnt2 = int.from_bytes(slave.input[2:4], byteorder='little', signed=False)
#print(f"cnt1={cnt1}")
label1.config(text=f"温度 值={cnt1/10}°C")
label2.config(text=f"湿度 值={cnt2/10}%")
time.sleep(0.01)
ethercat_thread = threading.Thread(target=thread1, daemon=True)
ethercat_thread.start()
root.mainloop()
print("程序已关闭.")
master.state = pysoem.INIT_STATE
# request INIT state for all slaves master.write_state()
master.close()
# *示例7和8
主要内容: 控制闭环步进电机,多电机同步控制。