2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Contact: Jeonghoon Park <jh1979.park@samsung.com>
6 * Licensed under the Flora License, Version 1.1 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://floralicense.org/license/
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include <peripheral_io.h>
22 #include "resource/resource_PCA9685.h"
23 #include "resource/resource_motor_driver_L298N.h"
27 MOTOR_STATE_CONFIGURED,
33 typedef struct __motor_driver_s {
37 motor_state_e motor_state;
38 peripheral_gpio_h pin1_h;
39 peripheral_gpio_h pin2_h;
42 static motor_driver_s g_md_h[MOTOR_ID_MAX] = {
43 {0, 0, 0, MOTOR_STATE_NONE, NULL, NULL},
47 /* see Principle section in http://wiki.sunfounder.cc/index.php?title=Motor_Driver_Module-L298N */
49 static int __motor_brake_n_stop_by_id(motor_id_e id)
51 int ret = PERIPHERAL_ERROR_NONE;
55 if (g_md_h[id].motor_state <= MOTOR_STATE_CONFIGURED) {
56 _E("motor[%d] are not initialized - state(%d)",
57 id, g_md_h[id].motor_state);
61 if (g_md_h[id].motor_state == MOTOR_STATE_STOP) {
62 _D("motor[%d] is already stopped", id);
66 if (g_md_h[id].motor_state == MOTOR_STATE_FORWARD) {
69 } else if (g_md_h[id].motor_state == MOTOR_STATE_BACKWARD) {
75 ret = peripheral_gpio_write(g_md_h[id].pin1_h, motor1_v);
76 if (ret != PERIPHERAL_ERROR_NONE) {
77 _E("Failed to set value[%d] Motor[%d] pin 1", motor1_v, id);
81 ret = peripheral_gpio_write(g_md_h[id].pin2_h, motor2_v);
82 if (ret != PERIPHERAL_ERROR_NONE) {
83 _E("Failed to set value[%d] Motor[%d] pin 2", motor2_v, id);
87 /* set stop DC motor */
88 // need to stop motor or not?, it may stop motor to free running
89 resource_pca9685_set_value_to_channel(g_md_h[id].en_ch, 0, 0);
91 g_md_h[id].motor_state = MOTOR_STATE_STOP;
96 static int __set_default_configuration_by_id(motor_id_e id)
100 unsigned int pin_1, pin_2, en_ch;
104 pin_1 = DEFAULT_MOTOR1_PIN1;
105 pin_2 = DEFAULT_MOTOR1_PIN2;
106 en_ch = DEFAULT_MOTOR1_EN_CH;
109 pin_1 = DEFAULT_MOTOR2_PIN1;
110 pin_2 = DEFAULT_MOTOR2_PIN2;
111 en_ch = DEFAULT_MOTOR2_EN_CH;
114 pin_1 = DEFAULT_MOTOR3_PIN1;
115 pin_2 = DEFAULT_MOTOR3_PIN2;
116 en_ch = DEFAULT_MOTOR3_EN_CH;
119 pin_1 = DEFAULT_MOTOR4_PIN1;
120 pin_2 = DEFAULT_MOTOR4_PIN2;
121 en_ch = DEFAULT_MOTOR4_EN_CH;
125 _E("Unkwon ID[%d]", id);
130 g_md_h[id].pin_1 = pin_1;
131 g_md_h[id].pin_2 = pin_2;
132 g_md_h[id].en_ch = en_ch;
133 g_md_h[id].motor_state = MOTOR_STATE_CONFIGURED;
139 static int __fini_motor_by_id(motor_id_e id)
141 retv_if(id == MOTOR_ID_MAX, -1);
143 if (g_md_h[id].motor_state <= MOTOR_STATE_CONFIGURED)
146 if (g_md_h[id].motor_state > MOTOR_STATE_STOP)
147 __motor_brake_n_stop_by_id(id);
149 resource_pca9685_fini(g_md_h[id].en_ch);
151 if (g_md_h[id].pin1_h) {
152 peripheral_gpio_close(g_md_h[id].pin1_h);
153 g_md_h[id].pin1_h = NULL;
156 if (g_md_h[id].pin2_h) {
157 peripheral_gpio_close(g_md_h[id].pin2_h);
158 g_md_h[id].pin2_h = NULL;
161 g_md_h[id].motor_state = MOTOR_STATE_CONFIGURED;
166 static int __init_motor_by_id(motor_id_e id)
170 retv_if(id == MOTOR_ID_MAX, -1);
172 if (g_md_h[id].motor_state == MOTOR_STATE_NONE)
173 __set_default_configuration_by_id(id);
175 ret = resource_pca9685_init(g_md_h[id].en_ch, 60);
177 _E("failed to init PCA9685");
181 /* open pins for Motor */
182 ret = peripheral_gpio_open(g_md_h[id].pin_1, &g_md_h[id].pin1_h);
183 if (ret == PERIPHERAL_ERROR_NONE)
184 peripheral_gpio_set_direction(g_md_h[id].pin1_h,
185 PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
187 _E("failed to open Motor[%d] gpio pin1[%u]. Error: %s", id, g_md_h[id].pin_1, get_error_message(ret));
191 ret = peripheral_gpio_open(g_md_h[id].pin_2, &g_md_h[id].pin2_h);
192 if (ret == PERIPHERAL_ERROR_NONE)
193 peripheral_gpio_set_direction(g_md_h[id].pin2_h,
194 PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
196 _E("failed to open Motor[%d] gpio pin2[%u]. Error: %s", id, g_md_h[id].pin_2, get_error_message(ret));
200 g_md_h[id].motor_state = MOTOR_STATE_STOP;
205 resource_pca9685_fini(g_md_h[id].en_ch);
207 _E("Motor init error: %s", get_error_message(ret));
209 if (g_md_h[id].pin1_h) {
210 peripheral_gpio_close(g_md_h[id].pin1_h);
211 g_md_h[id].pin1_h = NULL;
214 if (g_md_h[id].pin2_h) {
215 peripheral_gpio_close(g_md_h[id].pin2_h);
216 g_md_h[id].pin2_h = NULL;
222 void resource_close_motor_driver_L298N(motor_id_e id)
224 __fini_motor_by_id(id);
228 void resource_close_motor_driver_L298N_all(void)
231 for (i = MOTOR_ID_1; i < MOTOR_ID_MAX; i++)
232 __fini_motor_by_id(i);
237 int resource_set_motor_driver_L298N_configuration(motor_id_e id,
238 unsigned int pin1, unsigned int pin2, unsigned en_ch)
241 if (g_md_h[id].motor_state > MOTOR_STATE_CONFIGURED) {
242 _E("cannot set configuration motor[%d] in this state[%d]",
243 id, g_md_h[id].motor_state);
247 g_md_h[id].pin_1 = pin1;
248 g_md_h[id].pin_2 = pin2;
249 g_md_h[id].en_ch = en_ch;
250 g_md_h[id].motor_state = MOTOR_STATE_CONFIGURED;
255 int resource_set_motor_driver_L298N_speed(motor_id_e id, int speed)
258 const int value_max = 4095;
260 int e_state = MOTOR_STATE_NONE;
264 if (g_md_h[id].motor_state <= MOTOR_STATE_CONFIGURED) {
265 ret = __init_motor_by_id(id);
267 _E("failed to __init_motor_by_id()");
274 if (value > value_max) {
276 _D("max speed is %d", value_max);
278 _D("set speed %d", value);
282 ret = __motor_brake_n_stop_by_id(id);
284 _E("failed to stop motor[%d]", id);
291 e_state = MOTOR_STATE_FORWARD; /* will be set forward */
293 e_state = MOTOR_STATE_BACKWARD; /* will be set backward */
295 if (g_md_h[id].motor_state == e_state)
299 ret = __motor_brake_n_stop_by_id(id);
301 _E("failed to stop motor[%d]", id);
307 case MOTOR_STATE_FORWARD:
311 case MOTOR_STATE_BACKWARD:
316 ret = peripheral_gpio_write(g_md_h[id].pin1_h, motor_v_1);
317 if (ret != PERIPHERAL_ERROR_NONE) {
318 _E("failed to set value[%d] Motor[%d] pin 1", motor_v_1, id);
322 ret = peripheral_gpio_write(g_md_h[id].pin2_h, motor_v_2);
323 if (ret != PERIPHERAL_ERROR_NONE) {
324 _E("failed to set value[%d] Motor[%d] pin 2", motor_v_2, id);
329 ret = resource_pca9685_set_value_to_channel(g_md_h[id].en_ch, 0, value);
331 _E("failed to set speed - %d", speed);
335 g_md_h[id].motor_state = e_state;