mirror of https://github.com/arendst/Tasmota.git
Merge pull request #11005 from vic42/wemos_mtr_pr
Wemos Motor Shield V2 Support
This commit is contained in:
commit
deba1d3a46
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
xdrv_34_wemos_motor_v1.ino - Support for I2C WEMOS motor shield (6612FNG)
|
||||
|
||||
Copyright (C) 2021 Denis Sborets and Theo Arends
|
||||
Copyright (C) 2021 Denis Sborets, Theo Arends, Peter Franck
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,6 +21,7 @@
|
|||
#ifdef USE_WEMOS_MOTOR_V1
|
||||
/*********************************************************************************************\
|
||||
* WEMOS_MOTOR_V1 - DC motor driver shield (6612FNG) v 1.0.0
|
||||
* WEMOS_MOTOR_V2 - DC motor driver shield (6612FNG) v 2.0.0 (#define WEMOS_MOTOR_V2)
|
||||
*
|
||||
* I2C Address: 0x30
|
||||
*
|
||||
|
@ -28,10 +29,11 @@
|
|||
* driver44 <command>,<motor>,<direction>{,<duty>}
|
||||
* command:
|
||||
* RESET - reset a motor shield
|
||||
* SETMOTOR - seter motor state
|
||||
* SETMOTOR - set motor state
|
||||
* motor:
|
||||
* 0 - motor A
|
||||
* 1 - motor B
|
||||
* 2 - both motors (V2 only)
|
||||
* direction:
|
||||
* 0 - short break
|
||||
* 1 - CCW
|
||||
|
@ -61,6 +63,38 @@
|
|||
#define STOP 3
|
||||
#define STANDBY 4
|
||||
|
||||
#ifdef WEMOS_MOTOR_V2 // Support latest Lolin board
|
||||
// #define DEBUG_WEMOS_MOTOR // be more verbose
|
||||
#define WEMOS_MOTOR_PID_V2 0x02 // Product ID of V2.0.0
|
||||
#define WMTR_V2_BUFFSZ 5 // I2C command buffer size
|
||||
enum WEMOS_MOTOR_V2_CMD
|
||||
{
|
||||
WV2_GET_SLAVE_STATUS = 0x01,
|
||||
WV2_RESET_SLAVE,
|
||||
WV2_CHANGE_I2C_ADDRESS,
|
||||
WV2_CHANGE_STATUS,
|
||||
WV2_CHANGE_FREQ,
|
||||
WV2_CHANGE_DUTY
|
||||
};
|
||||
enum WEMOS_MOTOR_V2_STATUS
|
||||
{
|
||||
WV2_MOTOR_STATUS_STOP = 0x00,
|
||||
WV2_MOTOR_STATUS_CCW,
|
||||
WV2_MOTOR_STATUS_CW,
|
||||
WV2_MOTOR_STATUS_SHORT_BRAKE,
|
||||
WV2_MOTOR_STATUS_STANDBY
|
||||
};
|
||||
enum WEMOS_MOTOR_V2_CHANNEL
|
||||
{
|
||||
WV2_MOTOR_CH_A=0x00,
|
||||
WV2_MOTOR_CH_B,
|
||||
WV2_MOTOR_CH_BOTH
|
||||
};
|
||||
const char WemosMotorDriver[] = "WEMOS_MOTOR_V2";
|
||||
#else // WEMOS_MOTOR_V2
|
||||
const char WemosMotorDriver[] = "WEMOS_MOTOR_V1";
|
||||
#endif // WEMOS_MOTOR_V2
|
||||
|
||||
struct WMOTORV1 {
|
||||
bool detected = false;
|
||||
uint8_t motor;
|
||||
|
@ -69,31 +103,75 @@ struct WMOTORV1 {
|
|||
void WMotorV1Detect(void)
|
||||
{
|
||||
if (I2cSetDevice(WEMOS_MOTOR_V1_ADDR)) {
|
||||
#ifdef WEMOS_MOTOR_V2
|
||||
uint8_t i2c_data[WMTR_V2_BUFFSZ];
|
||||
// Check product ID & version
|
||||
i2c_data[0] = WV2_GET_SLAVE_STATUS;
|
||||
WMotorV2command(i2c_data, 1);
|
||||
if (i2c_data[0] == WEMOS_MOTOR_PID_V2) {
|
||||
#ifdef DEBUG_WEMOS_MOTOR
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("WEM: %s Rev. %u found"), WemosMotorDriver, i2c_data[1]);
|
||||
#endif // DEBUG_WEMOS_MOTOR
|
||||
} else { return; }
|
||||
#endif // WEMOS_MOTOR_V2
|
||||
WMotorV1.detected = true;
|
||||
I2cSetActiveFound(WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1");
|
||||
I2cSetActiveFound(WEMOS_MOTOR_V1_ADDR, WemosMotorDriver);
|
||||
WMotorV1Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void WMotorV1Reset(void)
|
||||
{
|
||||
// Wire.begin();
|
||||
WMotorV1SetFrequency(WEMOS_MOTOR_V1_FREQ);
|
||||
}
|
||||
|
||||
void WMotorV1SetFrequency(uint32_t freq)
|
||||
{
|
||||
#ifdef WEMOS_MOTOR_V2
|
||||
uint8_t i2c_data[WMTR_V2_BUFFSZ];
|
||||
i2c_data[0] = WV2_CHANGE_FREQ;
|
||||
i2c_data[1] = WV2_MOTOR_CH_BOTH;
|
||||
i2c_data[2] = (uint8_t)(freq & 0xff);
|
||||
i2c_data[3] = (uint8_t)((freq >> 8) & 0xff);
|
||||
i2c_data[4] = (uint8_t)((freq >> 16) & 0xff);
|
||||
WMotorV2command(i2c_data, 5);
|
||||
#else // WEMOS_MOTOR_V2
|
||||
Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR);
|
||||
Wire.write(((byte)(freq >> 16)) & (byte)0x0f);
|
||||
Wire.write((byte)(freq >> 16));
|
||||
Wire.write((byte)(freq >> 8));
|
||||
Wire.write((byte)freq);
|
||||
Wire.endTransmission(); // stop transmitting
|
||||
// delay(100);
|
||||
Wire.endTransmission();
|
||||
#endif // WEMOS_MOTOR_V2
|
||||
}
|
||||
|
||||
void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val)
|
||||
{
|
||||
#ifdef WEMOS_MOTOR_V2
|
||||
uint8_t i2c_data[WMTR_V2_BUFFSZ];
|
||||
// send command
|
||||
uint8_t cmd = dir;
|
||||
if (cmd == 0 || cmd == 3) {
|
||||
cmd ^= 3; // short brake and stop swapped
|
||||
}
|
||||
i2c_data[0] = WV2_CHANGE_STATUS;
|
||||
i2c_data[1] = (uint8_t)motor;
|
||||
i2c_data[2] = (uint8_t)cmd;
|
||||
WMotorV2command(i2c_data, 3);
|
||||
#ifdef DEBUG_WEMOS_MOTOR
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("WEM: Ch: %u Cmd: %u"), motor, cmd);
|
||||
#endif // DEBUG_WEMOS_MOTOR
|
||||
// set duty cycle
|
||||
uint16_t duty = (pwm_val > 100.0) ? 10000 : (uint16_t)(pwm_val * 100);
|
||||
#ifdef DEBUG_WEMOS_MOTOR
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("WEM: Duty: %u"), duty);
|
||||
#endif // DEBUG_WEMOS_MOTOR
|
||||
i2c_data[0] = WV2_CHANGE_DUTY;
|
||||
i2c_data[1] = (uint8_t)motor;
|
||||
i2c_data[2] = (uint8_t)(duty & 0xff);
|
||||
i2c_data[3] = (uint8_t)((duty >> 8) & 0xff);
|
||||
WMotorV2command(i2c_data,4);
|
||||
#else // WEMOS_MOTOR_V2
|
||||
Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR);
|
||||
Wire.write(motor | (byte)0x10);
|
||||
Wire.write(dir);
|
||||
|
@ -106,7 +184,7 @@ void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val)
|
|||
Wire.write((byte)(_pwm_val >> 8));
|
||||
Wire.write((byte)_pwm_val);
|
||||
Wire.endTransmission();
|
||||
// delay(100);
|
||||
#endif // WEMOS_MOTOR_V2
|
||||
}
|
||||
|
||||
bool WMotorV1Command(void)
|
||||
|
@ -132,8 +210,13 @@ bool WMotorV1Command(void)
|
|||
char *command = strtok(XdrvMailbox.data, ",");
|
||||
|
||||
if (strcmp(command, "RESET") == 0) {
|
||||
#ifdef WEMOS_MOTOR_V2 // do a 'real' reset
|
||||
uint8_t i2c_data[WMTR_V2_BUFFSZ];
|
||||
i2c_data[0] = WV2_RESET_SLAVE;
|
||||
WMotorV2command(i2c_data, 1);
|
||||
#endif // WEMOS_MOTOR_V2
|
||||
WMotorV1Reset();
|
||||
Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}"));
|
||||
Response_P(PSTR("{\"%s\":{\"RESET\":\"OK\"}}"), WemosMotorDriver);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -148,13 +231,39 @@ bool WMotorV1Command(void)
|
|||
}
|
||||
|
||||
WMotorV1SetMotor(motor, dir, duty);
|
||||
Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}"));
|
||||
Response_P(PSTR("{\"%s\":{\"SETMOTOR\":\"OK\"}}"), WemosMotorDriver);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WEMOS_MOTOR_V2
|
||||
void WMotorV2command(uint8_t *data, uint8_t len) // process V2 request
|
||||
{
|
||||
int i;
|
||||
Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR);
|
||||
for (i = 0; i < len; i++) {
|
||||
Wire.write(data[i]);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
|
||||
if (data[0] == WV2_GET_SLAVE_STATUS) {
|
||||
Wire.requestFrom(WEMOS_MOTOR_V1_ADDR, 2);
|
||||
} else {
|
||||
Wire.requestFrom(WEMOS_MOTOR_V1_ADDR, 1);
|
||||
}
|
||||
i = 0;
|
||||
bzero(data, WMTR_V2_BUFFSZ);
|
||||
while (Wire.available())
|
||||
{
|
||||
data[i] = Wire.read();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#endif // WEMOS_MOTOR_V2
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
|
Loading…
Reference in New Issue