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)
98 unsigned int pin_1, pin_2, en_ch;
102 pin_1 = DEFAULT_MOTOR1_PIN1;
103 pin_2 = DEFAULT_MOTOR1_PIN2;
104 en_ch = DEFAULT_MOTOR1_EN_CH;
107 pin_1 = DEFAULT_MOTOR2_PIN1;
108 pin_2 = DEFAULT_MOTOR2_PIN2;
109 en_ch = DEFAULT_MOTOR2_EN_CH;
112 pin_1 = DEFAULT_MOTOR3_PIN1;
113 pin_2 = DEFAULT_MOTOR3_PIN2;
114 en_ch = DEFAULT_MOTOR3_EN_CH;
117 pin_1 = DEFAULT_MOTOR4_PIN1;
118 pin_2 = DEFAULT_MOTOR4_PIN2;
119 en_ch = DEFAULT_MOTOR4_EN_CH;
123 _E("Unkwon ID[%d]", id);
128 g_md_h[id].pin_1 = pin_1;
129 g_md_h[id].pin_2 = pin_2;
130 g_md_h[id].en_ch = en_ch;
131 g_md_h[id].motor_state = MOTOR_STATE_CONFIGURED;
136 static int __fini_motor_by_id(motor_id_e id)
138 retv_if(id == MOTOR_ID_MAX, -1);
140 if (g_md_h[id].motor_state <= MOTOR_STATE_CONFIGURED)
143 if (g_md_h[id].motor_state > MOTOR_STATE_STOP)
144 __motor_brake_n_stop_by_id(id);
146 resource_pca9685_fini(g_md_h[id].en_ch);
148 if (g_md_h[id].pin1_h) {
149 peripheral_gpio_close(g_md_h[id].pin1_h);
150 g_md_h[id].pin1_h = NULL;
153 if (g_md_h[id].pin2_h) {
154 peripheral_gpio_close(g_md_h[id].pin2_h);
155 g_md_h[id].pin2_h = NULL;
158 g_md_h[id].motor_state = MOTOR_STATE_CONFIGURED;
163 static int __init_motor_by_id(motor_id_e id)
167 retv_if(id == MOTOR_ID_MAX, -1);
169 if (g_md_h[id].motor_state == MOTOR_STATE_NONE)
170 __set_default_configuration_by_id(id);
172 ret = resource_pca9685_init(g_md_h[id].en_ch);
174 _E("failed to init PCA9685");
178 /* open pins for Motor */
179 ret = peripheral_gpio_open(g_md_h[id].pin_1, &g_md_h[id].pin1_h);
180 if (ret == PERIPHERAL_ERROR_NONE)
181 peripheral_gpio_set_direction(g_md_h[id].pin1_h,
182 PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
184 _E("failed to open Motor[%d] gpio pin1[%u]", id, g_md_h[id].pin_1);
188 ret = peripheral_gpio_open(g_md_h[id].pin_2, &g_md_h[id].pin2_h);
189 if (ret == PERIPHERAL_ERROR_NONE)
190 peripheral_gpio_set_direction(g_md_h[id].pin2_h,
191 PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
193 _E("failed to open Motor[%d] gpio pin2[%u]", id, g_md_h[id].pin_2);
197 g_md_h[id].motor_state = MOTOR_STATE_STOP;
202 resource_pca9685_fini(g_md_h[id].en_ch);
204 if (g_md_h[id].pin1_h) {
205 peripheral_gpio_close(g_md_h[id].pin1_h);
206 g_md_h[id].pin1_h = NULL;
209 if (g_md_h[id].pin2_h) {
210 peripheral_gpio_close(g_md_h[id].pin2_h);
211 g_md_h[id].pin2_h = NULL;
217 void resource_close_motor_driver_L298N(motor_id_e id)
219 __fini_motor_by_id(id);
223 void resource_close_motor_driver_L298N_all(void)
226 for (i = MOTOR_ID_1; i < MOTOR_ID_MAX; i++)
227 __fini_motor_by_id(i);
232 int resource_set_motor_driver_L298N_configuration(motor_id_e id,
233 unsigned int pin1, unsigned int pin2, unsigned en_ch)
236 if (g_md_h[id].motor_state > MOTOR_STATE_CONFIGURED) {
237 _E("cannot set configuration motor[%d] in this state[%d]",
238 id, g_md_h[id].motor_state);
242 g_md_h[id].pin_1 = pin1;
243 g_md_h[id].pin_2 = pin2;
244 g_md_h[id].en_ch = en_ch;
245 g_md_h[id].motor_state = MOTOR_STATE_CONFIGURED;
250 int resource_set_motor_driver_L298N_speed(motor_id_e id, int speed)
253 const int value_max = 4095;
255 int e_state = MOTOR_STATE_NONE;
259 if (g_md_h[id].motor_state <= MOTOR_STATE_CONFIGURED) {
260 ret = __init_motor_by_id(id);
262 _E("failed to __init_motor_by_id()");
269 if (value > value_max) {
271 _D("max speed is %d", value_max);
273 _D("set speed %d", value);
277 ret = __motor_brake_n_stop_by_id(id);
279 _E("failed to stop motor[%d]", id);
286 e_state = MOTOR_STATE_FORWARD; /* will be set forward */
288 e_state = MOTOR_STATE_BACKWARD; /* will be set backward */
290 if (g_md_h[id].motor_state == e_state)
294 ret = __motor_brake_n_stop_by_id(id);
296 _E("failed to stop motor[%d]", id);
302 case MOTOR_STATE_FORWARD:
306 case MOTOR_STATE_BACKWARD:
311 ret = peripheral_gpio_write(g_md_h[id].pin1_h, motor_v_1);
312 if (ret != PERIPHERAL_ERROR_NONE) {
313 _E("failed to set value[%d] Motor[%d] pin 1", motor_v_1, id);
317 ret = peripheral_gpio_write(g_md_h[id].pin2_h, motor_v_2);
318 if (ret != PERIPHERAL_ERROR_NONE) {
319 _E("failed to set value[%d] Motor[%d] pin 2", motor_v_2, id);
324 ret = resource_pca9685_set_value_to_channel(g_md_h[id].en_ch, 0, value);
326 _E("failed to set speed - %d", speed);
330 g_md_h[id].motor_state = e_state;