由Austin Oltmanns创建,最后修改于2017年8月7日
欢迎再次来到这个关于DK-S124使用方法的系列教程。本指南将涵盖I2C外设的通用使用方法,以及Seeed对LSM6DS3(一款经济易用的IMU)扩展板的具体应用。DK-S124和六轴IMU(惯性测量单元,Seeed部件号105020012)均可在得捷电子购买。Renesas DK-S124:RTK7DKS124S00002BU;Seeed IMU:105020012。本指南假设您已完成入门指南,并对e2 studio有基本了解。不过,若有不清楚之处,将提供详细说明及先前指南的链接。一如既往,相关文档链接如下,以供参考。
这款特定传感器将易于使用,因为Renesas 已在板上提供了Grove连接器(但有一个注意事项,您将在下文看到)。此外,您可能会注意到开发板上已有一个加速度计;但是,没有陀螺仪。这使得在应用中测量任何类型的旋转变得不可能或非常困难,因此我们选择了六轴IMU作为替代。
对于此示例程序,我们将制作一个可重置的碰撞检测装置。其功能是轮询IMU,检测是否有超出预定义可接受范围的加速度/旋转。如果IMU确实报告了超出这些限制的情况,一个LED灯将被点亮,直到通过其中一个按钮按下重置为止。为此,将使用两个线程:一个用于读取传感器并在检测到碰撞时发布消息;另一个线程通过使用r_icu上的外部IRQ驱动程序,在接收到消息时点亮LED,在按下按钮(通过中断)时关闭LED,从而管理LED状态。
有用链接:
开发板用户手册:https://www.renesas.com/en-us/doc/products/renesas-synergy/doc/r12um0006eu0100-synergy-dk-s124.pdf
S124数据手册:https://www.renesas.com/en-us/doc/products/renesas-synergy/doc/r01ds0264eu0100_synergy_s124.pdf
S124用户手册:https://www.renesas.com/en-us/doc/products/renesas-synergy/doc/r01um0003eu0120-synergy-s124.pdf
Synergy软件包用户手册:RenesasSynergy™软件包(SSP)
Synergy软件平台基础书籍:https://www.renesas.com/en-us/media/products/synergy/book/Basics_of_the_Renesas_Synergy_Platform_1703.pdf
重要提示
:在撰写本文时,Renesas在DK-S124上存在一个设计错误,Grove I2C连接器被反向安装。因此,电源线和数据线的顺序被颠倒了。如果你使用Seeed提供的线缆连接IMU扩展板,它将无法工作!幸运的是,这通常不会损坏模块,但如果你在未先修改线缆/接头的情况下强行连接,则无法保证绝对安全。具体操作方法如下所述。
纠正错误
识别问题
首先要确认你的板子确实存在此问题。在未来的版本修订中,此错误可能会被修正。下图展示了错误的配置方式。
下图是根据Seeed(Grove接头的规范制定方)提供的标准正确配置示意图。
注意Renesas的接头方向是反的。
纠正此错误有以下几种方案。
- 将Renesas DK-S124上的接头解焊,按正确方向重新焊接。
- 将Seeed IMU上的接头解焊,按正确方向重新焊接。
- 剪断连接线,交换导线位置并焊接以确保良好连接。
- 用小螺丝刀撬开线缆接头一侧的金属触点,重新插入以制作交叉线缆。(最佳方案)
每种方案各有优劣。方案一能永久解决问题,但若操作不稳可能损坏开发板。方案二与方案一类似,但无法根本解决问题,且Seeed IMU采用表面贴装接头(触点已单向弯曲),操作难度高于DK-S124的通孔接头。此外,这仅解决当前IMU的问题,该线缆将无法用于其他标准Grove接口,可能成为最不推荐的方案。方案三操作简单,但会使线缆外观不美观。最后,方案四将在本指南中重点介绍,因为它对元件的风险最小,并能制作出优质的Grove交叉线缆(这种线缆本不应存在)。
调整触点位置
要将Seeed Grove线缆改造成Renesas Grove-Evorg交叉线缆,你需要一把能撬开塑料卡扣的小螺丝刀/撬棒,这些卡扣用于固定触点。
轻轻撬起塑料卡扣,拉动导线即可取出插座。对每一根导线,仅在一个且唯一一个连接器上执行此操作。然后,以相反顺序重新插入触点。完成后,您的IMU/电缆/开发板设置应如下图所示:
请注意,黑色线为GND,红色线为3.3V,黄色和白色线为I2C线路。DK-S124上的标签与颜色对应关系应与Seeed IMU上的标签与颜色对应关系一致。
配置线程与模块
硬件已正确配置完成,现在可以开始设置软件了。在e2 studio中创建一个新项目,记得选择正确的开发板(如果此步骤不熟悉,请参考EWFSDAFSAD)。接下来,打开项目配置选项卡并创建一个新线程。这将是I2C线程,当读取到加速度计数值超过特定阈值时(可用于碰撞检测或乘客安全警告),该线程将发布一条消息。
线程创建后,从Driver>Connectivity>I2C Master Driver on r_riic中添加I2C驱动程序。然后,对于此加速度计,设备从机地址为0x6A。请务必在I2C线程的属性部分更改此设置。
第二个要创建的线程是LED线程。此线程需要来自Framework>Services>Messaging Framework on sf_message的消息传递框架。添加后,将在添加下一个驱动程序后通过消息传递选项卡进行配置。此线程所需的另一个驱动程序是来自Driver>Input>External IRQ driver on r_icu的外部IRQ驱动程序。添加后,将通道更改为3(SW2所在的通道),将触发器设置为“下降沿”,将回调函数更改为“irq3_callback”,并将中断优先级设置为“优先级1”。接下来,转到引脚选项卡并展开端口部分。确保P004设置为输入模式,上拉电阻为无,IRQ为IRQ3。无需向此线程添加ioport驱动程序,因为该模块对整个应用程序是全局的,并且已存在于HAL/Common线程中。
接下来,转到配置页面的消息传递选项卡。创建一个名为“COLLISION”的事件类。将LED线程添加到订阅者列表中。至此,线程与模块的设置已完成,您可以保存配置文件并按下绿色的生成项目内容按钮。
添加代码
如果您从项目资源管理器中打开src目录,根据您为线程命名的不同,您应该会看到类似这样的内容。下一步是添加我们在上一组指令的“消息传递”选项卡中创建的自定义消息类型的头文件。右键单击“src”文件夹,然后导航到“新建>头文件”。将其命名为“collision_api.h”。用以下代码填充它:
collision_api.h
#ifndef COLLISION_API_H_
#define COLLISION_API_H_
#include "sf_message_api.h" //this is a message, so the message api is needed
typedef struct collision_payload_s
{
sf_message_header_t header; //every message must include a header of this type
uint8_t collision_type;
} collision_payload_t; //This name is specified in "Event Class" properties as "Payload Type"
#endif /* COLLISION_API_H_ */
接下来,将添加I2C线程的代码。该线程将通过I2C设置和轮询IMU,并在检测到碰撞时发布消息。关于通过I2C总线写入和接收的数据的具体信息,请参阅IMU的数据手册。
iic_thread_entry.c
#include "iic_thread.h"
#include "collision_api.h"
#define COLLISIONTHRESHOLD 25000
/* IIC Thread entry function */
void iic_thread_entry(void)
{
//sending conversions init
sf_message_header_t * pPostBuffer; //pointer for the buffer that must be acquired
sf_message_acquire_cfg_t acquireCfg = {.buffer_keep =false};
ssp_err_t errorBuff; //place for error codes from buffer acquisition to go
sf_message_post_err_t errPost; //place for posting error codes to go
sf_message_post_cfg_t post_cfg =
{
.priority = SF_MESSAGE_PRIORITY_NORMAL, //normal priority
.p_callback = NULL //no callback needed
};
collision_payload_t * pDataPayload; //pointer to the receiving message payload
g_i2c0.p_api->open(g_i2c0.p_ctrl, g_i2c0.p_cfg); //open the i2c peripheral
int8_t readbuffer[12]; // a place for the received data to go
uint8_t readaddress = 0x22; //the area in memory of the IMU to read
uint8_t accelconfigwrite[2] = {0x10, 0b01010000}; //the register and flags to set to configure the IMU
uint8_t gyroconfigwrite[2] = {0x11, 0b01010000}; //same
//see the IMU data sheet for details
uint8_t collisionstatus=0;
int16_t collisionmagnitude2 =0;
g_i2c0.p_api->write(g_i2c0.p_ctrl, &accelconfigwrite, 2,false); //write the configuration for the accelerometer
g_i2c0.p_api->write(g_i2c0.p_ctrl, &gyroconfigwrite, 2,false); //now for the gyroscope
while (1)
{
g_i2c0.p_api->write(g_i2c0.p_ctrl, &readaddress, 1, true); //write the address of memory we would like to read
g_i2c0.p_api->read(g_i2c0.p_ctrl, readbuffer, 12, false); //put the returned data in this buffer
//check squared magnitude of acceleration, square root is unnecessary as square is non-decreasing with magnitude
collisionmagnitude2 = readbuffer[7]*readbuffer[7] + readbuffer[9]*readbuffer[9] + readbuffer[11]*readbuffer[11];
if (collisionmagnitude2 > COLLISIONTHRESHOLD) collisionstatus =1;
if (collisionstatus !=0) //post a message if there was a collision
{
errorBuff = g_sf_message0.p_api->bufferAcquire(g_sf_message0.p_ctrl, &pPostBuffer, &acquireCfg, 300);
if (errorBuff==SSP_SUCCESS)
{
pDataPayload = (collision_payload_t *) pPostBuffer; //cast buffer to our payload
pDataPayload->header.event_b.class_code = SF_MESSAGE_EVENT_CLASS_COLLISION; //set the event class
pDataPayload->header.event_b.class_instance = 0; //set the class instance
pDataPayload->header.event_b.code = SF_MESSAGE_EVENT_NEW_DATA; //set the message type
pDataPayload->collision_type = collisionstatus;
g_sf_message0.p_api->post(g_sf_message0.p_ctrl, (sf_message_header_t *) pDataPayload,
&post_cfg, &errPost, TX_WAIT_FOREVER); //post the message
collisionstatus=0;
}
}
tx_thread_sleep (5);
}
}
最后,LED线程相对简单,应如下所示:
led_thread_entry.c
#include "led_thread.h"
#include "collision_api.h"
/* LED Thread entry function */
void irq3_callback(external_irq_callback_args_t * p_args)
{
g_ioport.p_api->pinWrite(IOPORT_PORT_01_PIN_07, IOPORT_LEVEL_LOW);
}
void led_thread_entry(void)
{
sf_message_header_t * pHeader; //pointer to the message header
collision_payload_t * thepayload; //pointer to the message payload
g_external_irq0.p_api->open(g_external_irq0.p_ctrl, g_external_irq0.p_cfg); //initialize the IRQ
while (1)
{
g_sf_message0.p_api->pend(g_sf_message0.p_ctrl, &led_thread_message_queue,
&pHeader, TX_WAIT_FOREVER); //wait for a message forever
if (pHeader->event_b.class_code == SF_MESSAGE_EVENT_CLASS_COLLISION) //if the message if the right kind
{
thepayload = (collision_payload_t *) pHeader; //cast the received message to the custom type
if (thepayload->header.event_b.code == SF_MESSAGE_EVENT_NEW_DATA) //if the message event is the right kind
{
g_ioport.p_api->pinWrite(IOPORT_PORT_01_PIN_07, IOPORT_LEVEL_HIGH);
g_sf_message0.p_api->bufferRelease(g_sf_message0.p_ctrl, pHeader, SF_MESSAGE_RELEASE_OPTION_NONE);
}
}
tx_thread_sleep (1);
}
}
结论
本示例展示了如何在Renesas DK-S124上使用和配置Grove Seeed I2C接口,以便与Seeed的LSM6DS3扩展板配合使用。本示例仅涵盖了加速度计的使用,而对于这个6轴传感器,陀螺仪的使用留给读者作为练习(此时应该很简单,寄存器数据已被读入内存;同时请注意,角速度可以简单地相加,因为它们是相互独立的)。此外,还简要介绍了外部中断的使用。
要测试本程序的功能,请尝试摇晃IMU,使绿灯亮起。可以更改阈值常量以调整灵敏度。为了测试本指南中的代码,我们将Renesas DK-S124和IMU放置在RC车上,并使其撞上几个障碍物。
问题 / 评论
如有任何问题或评论,请前往DigiKey技术论坛




