3030#include " configuration.h"
3131
3232#include < HomeGenie.h>
33+ #include < service/api/devices/Dimmer.h>
3334
3435#include " api/MotorHandler.h"
3536
@@ -40,9 +41,15 @@ StatusLed statusLed;
4041
4142using namespace IO ;
4243using namespace Service ;
44+ using namespace Service ::API ::devices;
4345
4446HomeGenie* homeGenie;
4547
48+ MotorHandler* motorHandler;
49+ bool is4wdRcCar;
50+ bool isRoboticArm;
51+ bool roboArmInitialized = false ;
52+
4653void setup () {
4754 // Default name shown in SNMP/UPnP advertising
4855 Config::system.friendlyName = " Smart Motor" ;
@@ -54,13 +61,144 @@ void setup() {
5461 statusLed.setup ();
5562#endif
5663
57- auto motorHandler = new MotorHandler ();
64+ motorHandler = new MotorHandler ();
5865 homeGenie->addAPIHandler (motorHandler);
5966
6067 homeGenie->begin ();
68+
69+ // Adds custom control modules
70+
71+ is4wdRcCar = Config::getSetting (" rc-car-4wd" ).equals (" true" );
72+ if (is4wdRcCar) {
73+
74+ // Add *Motion* and *Steering* control modules if this device is for the
75+ // FPV 4WD RC Car https://homegenie.it/mini/1.2/examples/fpv-rc-car/
76+
77+ // RC Car top view:
78+ //
79+ // (S4)-----(S3) - front wheels
80+ // | ... |
81+ // | ... |
82+ // (S2)-----(S1) - rear wheels (inverted mounting direction)
83+ //
84+ // - S1 = Servo Motor 1
85+ // - S2 = Servo Motor 2
86+ // - S3 = Servo Motor 3
87+ // - S4 = Servo Motor 4
88+
89+ auto list = motorHandler->getModuleList ();
90+ if (list->size () >= 4 ) {
91+ for (auto i = 0 ; i < 4 ; i++) {
92+ list->get (i)->setProperty (WidgetApi::Preference::HomeLevel, " 50" );
93+ list->get (i)->setProperty (WidgetApi::Preference::AutoHome, " true" );
94+ }
95+ // Module S1 to S4 are the 4WD motors
96+ auto motionControl = new Dimmer (IO ::IOEventDomains::Automation_Components, " MT1" , " Motion Control" );
97+ motionControl->module ->type = ModuleType::Motor;
98+ motionControl->module ->setProperty (WidgetApi::DisplayModule, " homegenie/generic/shutter" );
99+ motionControl->module ->setProperty (WidgetApi::Preference::HomeLevel, " 50" );
100+ motionControl->module ->setProperty (WidgetApi::Preference::AutoHome, " true" );
101+ motionControl->module ->setProperty (WidgetApi::Preference::LevelStep, " 2" );
102+ motionControl->setDefaultTransition (0 );
103+ motionControl->setLevel (0 .5f );
104+ motionControl->onSetLevel ([list](float level) {
105+ static float currentLevel = 0 ;
106+ if (level == currentLevel) {
107+ return ;
108+ }
109+ currentLevel = level;
110+ // move all 4WD motors
111+ // > 0.5 to 1.0 forward
112+ // < 0.5 to 0.0 backward
113+ // = 0.5 stopped
114+ auto s1 = list->get (0 );
115+ auto s2 = list->get (1 );
116+ auto s3 = list->get (2 );
117+ auto s4 = list->get (3 );
118+ level *= 100 ;
119+ ((MotorModule*) s1)->motorControl ->setLevel (100 - level);
120+ ((MotorModule*) s2)->motorControl ->setLevel (level);
121+ ((MotorModule*) s3)->motorControl ->setLevel (100 - level);
122+ ((MotorModule*) s4)->motorControl ->setLevel (level);
123+ });
124+ HomeGenie::getInstance ()->addAPIHandler (motionControl);
125+ auto steerControl = new Dimmer (IO ::IOEventDomains::Automation_Components, " ST1" , " Steering Control" );
126+ steerControl->module ->type = ModuleType::Motor;
127+ steerControl->module ->setProperty (WidgetApi::DisplayModule, " homegenie/generic/shutter" );
128+ steerControl->module ->setProperty (WidgetApi::Preference::HomeLevel, " 50" );
129+ steerControl->module ->setProperty (WidgetApi::Preference::AutoHome, " true" );
130+ steerControl->module ->setProperty (WidgetApi::Preference::LevelStep, " 2" );
131+ steerControl->setDefaultTransition (0 );
132+ steerControl->setLevel (0 .5f );
133+ steerControl->onSetLevel ([list](float level) {
134+ static float currentLevel = 0 ;
135+ Serial.println (level);
136+ if (level == currentLevel) {
137+ return ;
138+ }
139+ currentLevel = level;
140+ // Steering system
141+ // > 0.5 to 1.0 - steer right : move S1,S3 backward and S2,S4 forward
142+ // < 0.5 to 0.0 - steer left : move S1,S3 forward and S2,S4 backward
143+ // = 0.5 stopped
144+ auto s1 = list->get (0 );
145+ auto s2 = list->get (1 );
146+ auto s3 = list->get (2 );
147+ auto s4 = list->get (3 );
148+ level *= 100 ;
149+ ((MotorModule*) s1)->motorControl ->setLevel (level);
150+ ((MotorModule*) s2)->motorControl ->setLevel (level);
151+ ((MotorModule*) s3)->motorControl ->setLevel (level);
152+ ((MotorModule*) s4)->motorControl ->setLevel (level);
153+ });
154+ HomeGenie::getInstance ()->addAPIHandler (steerControl);
155+
156+ // initialize motors
157+ auto arm = std::vector<String>{" S1" , " S2" , " S3" , " S4" };
158+ for (const auto &addr: arm) {
159+ auto sm = motorHandler->getModule (IO ::IOEventDomains::Automation_Components, addr.c_str ());
160+ if (sm) {
161+ // "10" = max position seeking speed (1 - 10)
162+ ((MotorModule*) sm)->setProperty (Options::Motor_Servo_AngleSpeed, " 10" );
163+ // position to 50 (rest position)
164+ ((MotorModule*) sm)->motorControl ->setLevel (50 ); // (0-100)
165+ }
166+ }
167+ }
168+ }
169+
170+ isRoboticArm = Config::getSetting (" robotc-arm" ).equals (" true" );
171+ if (isRoboticArm) {
172+ // If this device is for the Robotic Arm only it will be using modules "S1" to "S4".
173+ // If this device is for RC-CAR with Robotic Arm, arm modules will be "S5" to "S8".
174+ // Configure Robotic Arm initial position to 0.5
175+ auto arm = !is4wdRcCar ? std::vector<String>{" S1" , " S2" , " S3" , " S4" } : std::vector<String>{" S5" , " S6" , " S7" , " S8" };
176+ for (const auto &addr: arm) {
177+ auto sm = motorHandler->getModule (IO ::IOEventDomains::Automation_Components, addr.c_str ());
178+ if (sm) {
179+ // max speed to seek initial position
180+ ((MotorModule *) sm)->setProperty (Options::Motor_Servo_AngleSpeed, " 10" );
181+ // position to 50 (rest position)
182+ ((MotorModule *) sm)->motorControl ->setLevel (50 ); // (0-100)
183+ }
184+ }
185+ }
186+
61187}
62188
63189void loop ()
64190{
65191 homeGenie->loop ();
192+
193+ if (isRoboticArm && !roboArmInitialized && millis () > 3000 ) {
194+ roboArmInitialized = true ;
195+ auto arm = !is4wdRcCar ? std::vector<String>{" S1" , " S2" , " S3" , " S4" } : std::vector<String>{" S5" , " S6" , " S7" , " S8" };
196+ for (const auto &addr: arm) {
197+ auto sm = motorHandler->getModule (IO ::IOEventDomains::Automation_Components, addr.c_str ());
198+ if (sm) {
199+ // set slower speed for normal operations (smoother movements)
200+ sm->setProperty (Options::Motor_Servo_AngleSpeed, " 5" );
201+ }
202+ }
203+ }
66204}
0 commit comments