最近EPS測驗設備有個扭矩傳感器在使用,輸出信號是5kHz~15kHz,對應的扭矩是-100Nm~100Nm,打算用Arduino采集這個信號。由于有Vector 的CANoe,希望把采到的信號發到CAN bus上,然后在CANoe上顯示。
為了測驗,買了個CAN-shield板,兼容UNO。測驗的時候先不連扭矩傳感器,先用UNO模擬輸出PWM。因為arduino的anlogWrite()發送的PWM頻率沒法更改,所以網上查了下手動配置的方法,用的是修改上限的快速PWM方式。
硬體:Arduino UNO R3;CAN-shield V2.0;

1、修改上限快速PWM輸出
參考Aduino官方PWM檔案和ATMEL328P的datasheet
修改上限快速PWM如果用TIMER2計時器的話,對應的輸出腳是3,11。3對應的是OCB輸出,11對應的是OCA輸出,這個模式下的OCB作為輸出,OCA只能當成輸出占空比固定為50%的PWM。本次用3當輸出。用12當輸入。
int pin1=3;//output;OCCRA控制11腳,OCCRB控制3腳
int pin2=12;//input
然后是對四個暫存器TCCR2A,TCCR2B,OCCR2A,OCCR2B進行設定,預分頻選1/8,就是在TCCR2B里設定CS21。這樣輸出的頻率正好在5khz~15khz里。其它具體的設定方法抄在代碼注釋里了。
2、用CAN Shield V2.0把模擬的扭矩報文發CAN bus
CAN Shield對應的庫檔案,MS-CAN。直接呼叫就好了。為了便于后續CAN分析設備(PCAN,Vector CANoe等等)讀報文,把扭矩信號轉成0~10000的數,解析度0.01,分在兩個byte里,方向用個direction信號發,然后是0~255的counter和一個checksum。
3、測驗效果
用PCAN讀CAN Shield發的報文,用串口監視器讀頻率,扭矩的信號,對比一下,輸出是正常的。

/*
模擬扭矩傳感器輸出頻率信號,并采集該信號轉換成合適的資料發送至CAN BUS
- 針腳定義:3號腳輸出頻率脈沖,12號腳采集頻率脈沖:10號腳SPI_CS
- 信號轉換:扭矩傳感器5khz~15hz 對應 -100Nm~100Nm;將扭矩信號
轉換成0.01解析度,無符號型別,即扭矩CAN信號0~10000(0x0~0x2710),
方向用direction信號發出,>=0為1,<0為0。
- 頻率信號模擬方式:快速PWM,修改時鐘的計數上限
B(3腳)輸出占空比可控信號,A輸出固定占空比(50%)且頻率為B的一半
*/
#include <df_can.h>
#include <SPI.h>
const int SPI_CS_PIN = 10;// Set CS pin
MCPCAN CAN(SPI_CS_PIN);
int pin1=3;//output;OCCRA控制11腳,OCCRB控制3腳
int pin2=12;//input
double duration; //高電平持續時間us
double lowlevel; //低電平持續時間us
double OutputDuty;//輸出的占空比
double period; //脈沖周期
double freq; //脈沖頻率
double torque; //帶符號扭矩值
int torque_send; //扭矩取絕對值
int torque_direction; //扭矩方向
char data_to_PC;
byte count=0; //message counter
byte checksum=0; //message checksum
byte torque_send_high=0; //高8位元組
byte torque_send_low=0; //扭矩低8位元組
void setup()
{
// put your setup code here, to run once:
pinMode(pin1,OUTPUT); //3腳輸出
pinMode(pin2,INPUT); //12腳輸入
//以下對Timer2進行設定,詳見ATMEL328P datasheet
TCCR2A=_BV(COM2A0)|_BV(COM2B1)|_BV(WGM21)|_BV(WGM20);//COM2A0輸出A在到TOP輸出反相;COM2B1 輸出的B不反;WGM設定為111,即快速PWM控制計數上限
TCCR2B=_BV(WGM22)|_BV(CS21);//預分頻為010:8分頻
/*
TCCR2A
Bit 7 6 5 4 3 2 1 0
COM2A1 COM2A0 COM2B1 COM2B0 - - WGM21 WGM20
Compare Output Mode,Fast PWM Mode:
COM2A1 COM2A0
0 0 Nomal port operation,OC2A disconnected
0 1 WGM22=0:Normal port operation,OC0A disconnected;WGM22=1:Toggle OC2A on compare match
1 0 Clear OC2A on compare match,set OC2A at BOTTOM(non-inverting mode)
1 1 Set OC2A on compare match,clear OC2A at BOTTOM(inverting mode)
COM2B1 COM2B0
0 0 Normal port operation,OC2B disconnected
0 1 Reserved
1 0 Clear OC2B on compare match,set OC2B at BOTTOM(non-inverting mode)
1 1 Set OC2B on compare match,clear OC2B at BOTTOM(inverting mode)
Mode WGM22 WGM21 WGM20 ||Timer/Counter Mode of Operation || TOP || Update of OCRx at || TOV Flag Set on
0 0 0 0 Normal 0xFF Immediate MAX
1 0 0 1 PWM,phase correct 0xFF TOP BOTTOM
2 0 1 0 CTC OCRA Immediate MAX
3 0 1 1 Fast PWM 0xFF BOTTOM MAX
4 1 0 0 Reserved - - -
5 1 0 1 PWM,phase correct OCRA TOP BOTTOM
6 1 1 0 Reserved - - -
7 1 1 1 Fast PWM OCRA BOTTOM TOP
TCCR2B
Bit 7 6 5 4 3 2 1 0
FOC2A FOC2B - - WGM22 CS22 CS21 CS20
Clock Select Bit Description
CS22 CS21 CS20 Description
0 0 0 No clock source(Timer/Counter stopped)
0 0 1 clkT2s/(no prescaling)
0 1 0 clkT2s/8(from prescaler)
0 1 1 clkT2s/32(from prescaler)
1 0 0 clkT2s/64(from prescaler)
1 0 1 clkT2s/128(from prescaler)
1 1 0 clkT2s/256(from prescaler)
1 1 1 clkT2s/1024(from prescaler)
*/
OCR2A=249;//修改時鐘計數上限模式下,控制計數上限
OCR2B=50;//控制match的計數點
/*
頻率計算:
B:16M/8/(249+1)=8000Hz
A:16M/8/(249+1)/2=4000Hz
占空比計算:
B:(50+1)/(249+1)=20.4%
A:固定的50%
*/
Serial.begin(19200);
int count = 50; // the max numbers of initializint the CAN-BUS, if initialize failed first!.
do {
CAN.init(); //must initialize the Can interface here!
if(CAN_OK == CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println(CAN BUS Shield init ok!");
break;
}
else
{
Serial.println(CAN BUS Shield init fail");
Serial.println("Please Init CAN BUS Shield again");
delay(100);
if (count <= 1)
Serial.println("Please give up trying!, trying is useless!");
}
}while(count--);
}
void loop() {
// put your main code here, to run repeatedly:
//采集波形高電平階段時間,及低電平階段時間
duration=pulseIn(pin2,HIGH);
lowlevel=pulseIn(pin2,LOW);
OutputDuty=CalculateOutputDuty(duration,lowlevel);//呼叫占空比計算函式
period=duration+lowlevel; //周期=高電平加低電平時間
freq=1/period*1000000; //頻率=1/周期 (周期單位是us,所以頻率要乘10^6)
torque=CalculateTorque(duration,lowlevel);//呼叫計算扭矩函式
//扭矩方向信號計算
if(torque>=0)
{
torque_direction=1;
}
if(torque<0)
{
torque_direction=0;
}
//發送的扭矩信號為絕對值,無符號
torque_send=abs(torque*100);
if(5000<=freq<=15000)
{
//用byte強制轉換格式為一個位元組,把高8位去掉
torque_send_low=byte(torque_send);
//把2位元組右移8位,把低8位去掉
torque_send_high=byte(torque_send>>8);
}
if((freq<5000)||(freq>15000))
{
torque_send_low=0xFF;
torque_send_high=0xFF;
}
while(Serial.available()>0)
{
data_to_PC=Serial.read();
if (data_to_PC=='s')//串口除錯助手輸入s并發送后列印資料
{
Serial.println("");
Serial.print("The output duty is:");
Serial.print(OutputDuty);
Serial.println("%");
Serial.print("The High level interval is:");
Serial.print(duration);
Serial.println("us");
Serial.print("The Low level interval is:");
Serial.print(lowlevel);
Serial.println("us");
Serial.print("The period is:");
Serial.print(period);
Serial.println("us");
Serial.print("The freq is:");
Serial.print(freq);
Serial.println("Hz");
Serial.print("The Torque_send is:");
Serial.print(torque_send);
Serial.println("");
Serial.print("The Torque Direction is:");
Serial.println(torque_direction);
}
}
//counter0~255回圈
if(count<=0xFF)
{
count++;
}
if(count>0xFF)
{
count=0;
}
//checksum 為前7位元組異或演算法
checksum=torque_send_high^torque_send_low^torque_direction^0x0^0x0^0x0^count;
//data[]定義報文的8個位元組資料
unsigned char data[8]={torque_send_high, torque_send_low, torque_direction, 0x0, 0x0, 0x0, count, checksum};
//用sendMsgBuf(ID,extended message or not,data length,data)函式發送報文報文 ID:0x111 報文型別:0為資料幀 長度:8位元組
CAN.sendMsgBuf(0x111, 0, 8, data);
delay(20); // send data per 20ms
}
double CalculateOutputDuty(double i,double j)
{
double cal;
cal=i/(i+j)*100;
return cal;
}
double CalculateTorque(double high,double low)
{
double cal_torque;
cal_torque=(freq-10000)/5000*100;
return cal_torque;
}
uj5u.com熱心網友回復:
太好了,正需要這方面的資料。轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/47362.html
標籤:單片機/工控
上一篇:計算機網路協議基礎
下一篇:求個華三Ap的韌體,萬分感謝
