本案例主要讲述了使用GoKit和GC211(4G模块)来实现4G网络的开发。囊括模块接入、设备控制、数据采集、APP开发等方面内容。难度较低,适合新手入门。另外本次内容篇幅较长,将分成五部分来连载。主要是以图文形式呈现,如在实践过程中有疑问,可以加入机智云QQ群一起沟通探讨。
本文是连载第三篇!讲的是Arduino版块的移植,让GoKit实现和APP、云端的互联互通。当然,如果你对Arduino不感兴趣,可以不看这个。只看第二篇就够了。
连载教程内容:
♦ Arduino作为主控实现GOKIT全功能控制和采集
♦ 新版本APP快速开发
♦ 网页控制GOKIT开发板
Arduino代码移植编写
通过这一步骤,我们要了解驱动下载地址、如何移植代码,如电机控制、颜色变化、函数初始化等,移植好代码后,为后续的APP应用开发奠定基础。
1.下载Arduino驱动文件,机智云下载中心下载。
2.将下载的驱动文件解压,将芯片驱动文件复制到安装好的arduino软件的..\libraries目录下。
3.将下载的代码进行解压,复制Gizwits到arduino 软件的.. \libraries目录下。
4. 使用arduino软件打开下载自动生成代码下载的文件中 MCU_ArduinoUNOR3_source\examples\simpleTry\simpleTry.ino ,然后添加各驱动库的头文件,以及全局变量。
#include <DHT.h>
#include <ChainableLED.h>
#include <MsTimer2.h>
/*************************** HAL define ***************************/
#define Infrared_PIN 2 ///< 红外IO管脚
#define DHTPIN 3 ///< 温湿度IO管脚
#define MOTOR_PINA 4 ///< 电机IO管脚
#define MOTOR_PINB 5 ///< 电机IO管脚
#define KEY1 6 ///< 按键IO管脚
#define KEY2 7 ///< 按键IO管脚
//温湿度功能值定义
#define DHTTYPE DHT11
//电机功能值定义
#define MOTOR_MAX 100
#define MOTOR_MAX1 ‐100
#define MOTOR_MIN 0
#define MOTOR_16
//按键功能值定义
#define KEY1_SHORT_PRESS 1
#define KEY1_LONG_PRESS 2
#define KEY2_SHORT_PRESS 4
#define KEY2_LONG_PRESS 8
#define NO_KEY 0
#define KEY_LONG_TIMER 3
unsigned long Last_KeyTime = 0;
uint8_t NetConfigureFlag = 0;
uint8_t gaterSensorFlag = 0;
typedef enum
{
LED_Costom = 0x00,
LED_Yellow = 0x01,
LED_Purple = 0x02,
LED_Pink = 0x03,
} LED_ColorTypeDef;
DHT dht(DHTPIN, DHTTYPE);
ChainableLED leds(A5, A4, 1);
5. 在simpleTry.ino文件中添加温湿度传感器数据获取的函数。
void DHT11_Read_Data(unsigned char * temperature, unsigned char * humidity)
{
*temperature = (unsigned char)dht.readTemperature();
*humidity = (unsigned char)dht.readHumidity();
return;
}
6. 在simpleTry.ino文件中添加控制电机的驱动函数
void Motor_status(long motor_speed)
{
unsigned char Temp_motor_speed = 0;
if (motor_speed == 0) //停止????
{
digitalWrite(MOTOR_PINA, LOW);
digitalWrite(MOTOR_PINB, LOW);
}
if (motor_speed > 0) //正转
{
Temp_motor_speed = (motor_speed ‐ 0) * 51;
if (Temp_motor_speed > 255) Temp_motor_speed = 255;
digitalWrite(MOTOR_PINA, LOW);
analogWrite( MOTOR_PINB, Temp_motor_speed);
}
if (motor_speed < 0) //反转
{
Temp_motor_speed = 255 ‐ (0 ‐ motor_speed) * 51; //Temp_motor_speed = (255 ‐ (5 + motor_speed))
* 51;
if (Temp_motor_speed > 255) Temp_motor_speed = 255;
digitalWrite(MOTOR_PINA, HIGH);
analogWrite( MOTOR_PINB, Temp_motor_speed );
}
}
7. 在simpleTry.ino文件中添加RGB LED控制函数
void LED_RGB_Control(byte red, byte green, byte blue)
{
leds.setColorRGB(0, red, green, blue);
}
8. 在simpleTry.ino文件中添加按键控制的驱动函数。
unsigned long gokit_time_s(void)
{
return millis() / 1000;
}
char gokit_key1down(void)
{
unsigned long keep_time = 0;
if (digitalRead(KEY1) == LOW)
{
delay(100);
if (digitalRead(KEY1) == LOW)
{
keep_time = gokit_time_s();
while (digitalRead(KEY1) == LOW)
{
if ((gokit_time_s() ‐ keep_time) > KEY_LONG_TIMER)
{
Last_KeyTime = gokit_time_s();
return KEY1_LONG_PRESS;
}
} //until open the key
if ((gokit_time_s() ‐ Last_KeyTime) > KEY_LONG_TIMER)
{
return KEY1_SHORT_PRESS;
}
return 0;
}
return 0;
}
return 0;
}
char gokit_key2down(void)
{
int unsigned long keep_time = 0;
if (digitalRead(KEY2) == LOW)
{
delay(100);
if (digitalRead(KEY2) == LOW)
{
keep_time = gokit_time_s();
while (digitalRead(KEY2) == LOW) //until open the key
{
if ((gokit_time_s() ‐ keep_time) > KEY_LONG_TIMER)
{
Last_KeyTime = gokit_time_s();
return KEY2_LONG_PRESS;
}
}
if ((gokit_time_s() ‐ Last_KeyTime) > KEY_LONG_TIMER)
{
return KEY2_SHORT_PRESS;
}
return 0;
}
return 0;
}
return 0;
}
char gokit_keydown(void)
{
char ret = 0;
ret |= gokit_key2down();
ret |= gokit_key1down();
return ret;
}
void KEY_Handle(void)
{
/* Press for over than 3 second is Long Press */
switch (gokit_keydown())
{
case KEY1_SHORT_PRESS:
Serial.println(F("KEY1_SHORT_PRESS , Production Test Mode "));
myGizwits.setBindMode(WIFI_PRODUCTION_TEST);
break;
case KEY1_LONG_PRESS:
Serial.println(F("KEY1_LONG_PRESS ,Wifi Reset"));
myGizwits.setBindMode(WIFI_RESET_MODE);
break;
case KEY2_SHORT_PRESS:
Serial.println(F("KEY2_SHORT_PRESS Soft AP mode"));
myGizwits.setBindMode(WIFI_SOFTAP_MODE);
///< 进入Soft AP mode RGB LED亮红灯
NetConfigureFlag = 1; ///< 等待连接路由的标志位
LED_RGB_Control(100, 0, 0); ///< 红绿灯
break;
case KEY2_LONG_PRESS:
Serial.println(F("KEY2_LONG_PRESS ,AirLink mode"));
myGizwits.setBindMode(WIFI_AIRLINK_MODE);
///< 进入AirLink mode RGB LED亮绿灯
NetConfigureFlag = 1; ///< 等待连接路由的标志位
LED_RGB_Control(0, 100, 0); ///< 亮绿灯
break;
default:
break;
}
}
9. 在simpleTry.ino文件中添加WiFi状态事件触发函数
void wifiStatusHandle()
{
if(myGizwits.wifiHasBeenSet(WIFI_SOFTAP))
Serial.println(F("WIFI_SOFTAP!"));
if(myGizwits.wifiHasBeenSet(WIFI_AIRLINK))
Serial.println(F("WIFI_AIRLINK!"));
if(myGizwits.wifiHasBeenSet(WIFI_STATION))
Serial.println(F("WIFI_STATION!"));
if(myGizwits.wifiHasBeenSet(WIFI_CON_ROUTER))
{
Serial.println(F("WIFI_CON_ROUTER!"));
if(1 == NetConfigureFlag)
{
LED_RGB_Control(0, 0, 0); ///< Airlink配置成功即模组连接到路由后关闭绿灯
NetConfigureFlag = 0;
}
}
if(myGizwits.wifiHasBeenSet(WIFI_DISCON_ROUTER))
Serial.println(F("WIFI_DISCON_ROUTER!"));
if(myGizwits.wifiHasBeenSet(WIFI_CON_M2M))
Serial.println(F("WIFI_CON_M2M!"));
if(myGizwits.wifiHasBeenSet(WIFI_DISCON_M2M))
Serial.println(F("WIFI_DISCON_M2M!"));
}
10. 在simpleTry.ino文件中添加只读型数据点相关的处理代码
void GizWits_GatherSensorData(void)
{
uint8_t curTem, curHum;
bool Infrared;
//获取红外传感器IO的高低电平状态
if (digitalRead(Infrared_PIN))
{
Infrared = 0;
}
else
{
Infrared = 1;
}
//获取温湿度传感器的数值
DHT11_Read_Data(&curTem, &curHum);
myGizwits.write(VALUE_INFRARED, Infrared); ///< 上报红外状态数据
myGizwits.write(VALUE_TEMPERATURE, (long)curTem); ///< 上报温度数据
myGizwits.write(VALUE_HUMIDITY, (unsigned long)curHum); ///< 上报湿度数据
}
void gokit_timer(void)
{
static long gaterTime = 0;
gaterTime++;
if(gaterTime >= 1000)
{
gaterTime = 0;
gaterSensorFlag = 1;
}
}
11. 在 simpleTry.ino 文件中的loop()函数中添加 间隔一秒的状态机调用,gokit_timer() 函数实现了周期性(这里间隔1秒)获取只读类型数据点的的数据,它是由初始化时的定时器实现的。每隔1秒设置一次gaterSensorFlag 标志位,然后触发 loop() 中的GizWits_GatherSensorData 标志进行数据采集。如果在 loop() 中直接调用例如温湿度这样的时序实现的驱动函数的话,由于loop执行过快会造成读传感器的异常,同时也避免了上报数据过频繁造成的问题 。
if (gaterSensorFlag != 0)
{
GizWits_GatherSensorData();
gaterSensorFlag = 0;
}
12. 在simpleTry.ino文件中的loop()函数中添加可写型传感器数据点相关的处理代码,通过myGizwits.hasBeenSet()这个方法判断这个数据点事件有是否发生,如果数据点事件发生了就通过myGizwits.read()这个方法把发生的事件所产生的数据读取出来,然后再做相应的判断。
13. 在simpleTry.ino文件中的loop()函数中添加WiFi状态事件触发函数 、按键控制的驱动函数的调用。
14. 在simpleTry.ino文件的setup( )函数中添加各sensor的初始化
Serial.begin(9600);
myGizwits.begin();
///< 温度传感初始
dht.begin();
///< RGB LED初始
leds.init();
digitalWrite(A0, HIGH);//使能RGB LED
///< 新添加代码: 按键初始
pinMode(KEY1, INPUT_PULLUP); //KEY1 上拉输入
pinMode(KEY2, INPUT_PULLUP); //KEY2 上拉输入
///< 电机初始化
pinMode(MOTOR_PINA, OUTPUT);
pinMode(MOTOR_PINB, OUTPUT);
digitalWrite(MOTOR_PINB, LOW);
digitalWrite(MOTOR_PINA, LOW);
Motor_status(0);
//定时中断初始
MsTimer2::set(1, gokit_timer); // 1ms period
MsTimer2::start();
15. 编写完成之后将代码上传到开发板。特别提示,不要再网页上复制代码,否则大小或者写不对会导致编译无法通过,可参考源文件中的代码。
然后按照第二篇文档STM32方式连接开发板即可,到此教程结束。