├── .github
└── FUNDING.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── examples
├── App
│ ├── OttoNinja_APP
│ │ └── OttoNinja_APP.ino
│ ├── OttoNinja_APP_OLED
│ │ └── OttoNinja_APP_OLED.ino
│ └── OttoNinja_App_matrix
│ │ └── OttoNinja_App_matrix.ino
├── Humanoid
│ ├── OttoNinjaHumanoid_Avoid
│ │ └── OttoNinjaHumanoid_Avoid.ino
│ └── OttoNinjaHumanoid_Demo
│ │ └── OttoNinjaHumanoid_Demo.ino
├── LED matrix
│ ├── OttoE_alleyes
│ │ └── OttoE_alleyes.ino
│ ├── OttoE_flappybird
│ │ └── OttoE_flappybird.ino
│ ├── OttoE_rolleyes
│ │ └── OttoE_rolleyes.ino
│ ├── OttoE_soundlevels
│ │ └── OttoE_soundlevels.ino
│ └── Snake8x8matrix
│ │ ├── Snake8x8matrix.ino
│ │ └── buttons.ino
└── Starter
│ └── OttoNinja_Theremin
│ └── OttoNinja_Theremin.ino
├── keywords.txt
├── library.json
├── library.properties
└── src
├── RemoteXY.h
├── RemoteXYApi.h
├── RemoteXYApiData.h
├── RemoteXYCloudServer.h
├── RemoteXYComm.h
├── RemoteXYComm_AT.h
├── RemoteXYComm_ESP8266.h
├── RemoteXYComm_Ethernet.h
├── RemoteXYComm_WiFi.h
├── RemoteXYConnection.h
├── RemoteXYConnectionCloud.h
├── RemoteXYConnectionServer.h
├── RemoteXYConnectionStream.h
├── RemoteXYDebugLog.h
├── RemoteXYFunc.h
├── RemoteXYStream.h
├── RemoteXYStream_BLEDevice.h
├── RemoteXYStream_BLEPeripheral.h
├── RemoteXYStream_BluetoothSerial.h
├── RemoteXYStream_CDCSerial.h
├── RemoteXYStream_HardSerial.h
├── RemoteXYStream_SoftSerial.h
├── RemoteXYThread.h
├── RemoteXYWire.h
├── RemoteXYWireCloud.h
└── RemoteXYWireStream.h
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute to OttoDIY effectively?
2 | Otto Builders are the community of Otto DIY.
3 |
4 | ## 1. step one is become an Otto Builder
5 |
6 | Be a part of this friendly community of robot builders, teachers and makers!
7 |
8 | * [Group in Facebook](https://www.facebook.com/groups/ottodiy/)
9 | * [Like our Facebook page](https://www.facebook.com/ottodiy/)
10 | * [Subscribe to our YouTube channel](https://www.youtube.com/c/ottodiy?sub_confirmation=1)
11 | * [Follow us in Instagram](https://www.instagram.com/ottodiy/)
12 | * [and Twitter](https://twitter.com/ottodiy)
13 |
14 | Welcome to our Otto Builder community!
15 |
16 | ## 2. step two is to build your own Otto!
17 | Start with the basic if you are a beginner; Otto DIY can be made easily with [our Builder Kit (full with 3D printed parts)](https://ottodiy.ecwid.com/Otto-DIY-Builder-Kit-p135022769) or [Maker Kit (only electronics) if you have a 3D printer](https://ottodiy.ecwid.com/Otto-DIY-Maker-Kit-p135022782).
18 |
19 | Once you feel more confident you can [jump to any of our other Otto robots](https://ottodiy.ecwid.com/) with more advanced features and sensors.
20 |
21 | ## 3. step three Make your contribution
22 |
23 | If you noticed we have @divided our documenation in [Wikifactory](https://wikifactory.com/+OttoDIY/projects) and [Github](https://github.com/OttoDIY/), this is because one tool is good for hardware the other for merely software, we also find out that one is easier to use for our main community audience but feel free to use any you feel comfortable with, currently we need support with:
24 |
25 | * New Remixes or designs of similar robots you can just upload into Wikifactory Otto DIY projects [submit any creation you have made here](https://wikifactory.com/new-project) they help show the projects possibility and community collaboration.
26 | * Language [translations for our Otto Blockly](https://github.com/OttoDIY/blockly) with this more people will learn how to code.
27 | * In the same repository you can help us report issues or solve them or pull request other improvements.
28 | * Ideas or [improvements for our mobile App!](https://github.com/OttoDIY/OttoDIYApp)
29 |
30 | or just send us the files we will upload for you and give the appropriate credits to you.
31 |
32 | Happy to have you as a part of the Otto Community :) and thanks!
33 |
34 | ## 4. Share with #OttoDIY
35 |
36 | to have more visibility keep sharing with us in any of our social media, friends, family [#OttoDIY](https://twitter.com/search?q=%23OttoDIY&src=typd&lang=en) and make sure more Otto Builders do the same everywhere. We love to see Ottos around the world!
37 | help us please to spread the word in Maker Faires, maker spaces, hacker spaces, schools and so on, We are rewarding the best Otto builders with kits!
38 |
39 | [check our Forum for questions.](https://wikifactory.com/+OttoDIY/forum)
40 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Issue Template
2 |
3 | ## Explain the problem:
4 |
5 | *Is it a code issue? - make sure you are using the right libraries and Mblock or Arduino software, please post a screenshot.
6 |
7 | *Is it an electronic issue? - please post a complementary picture.
8 |
9 | *Is it a 3D print issue? - In the case of 3D print improvement please post in thingiverse.
10 |
11 | If solved please share the solution.
12 |
13 | Thanks #Ottobuilder
14 |
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Otto DIY
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Otto Ninja Robot Arduino Libraries
2 |
3 | [](https://www.gnu.org/licenses/gpl-3.0)
4 | 
5 |
6 | This repository has the main [Otto Ninja robot](https://www.ottodiy.com/ninja) libraries for ESP compatible boards.
7 |
8 | ## Compatible Hardware
9 |
10 | - Designed to work with ESP8266 boards, but most of the code could be adapted to other microcontrollers.
11 |
12 | You will need to [add the ESP8266 to your Arduino IDE](https://randomnerdtutorials.com/how-to-install-esp8266-board-arduino-ide/)
13 |
14 | :star: Star us on GitHub; it helps!
15 |
16 | ## Installation:
17 |
18 | You will need the [Arduino IDE on your computer](https://www.arduino.cc/en/software)
19 |
20 | 1. [Download Otto Ninja libraries here](https://github.com/OttoDIY/OttoNinja/archive/master.zip)
21 | 2. Open the Arduino IDE and navigate to Sketch > Include Library > Add .ZIP Library...
22 | 3. Navigate to .zip file location that you just downloaded and open it.
23 | 4. You will see in the bottom black area a message that it has been installed.
24 | 5. To verify they are properly installed, go to Sketch > Include Library menu. You should now see the library at the bottom of the drop-down menu.
25 |
26 | ## Example:
27 |
28 | You can find codes in File > Examples > OttoNinja.
29 |
30 | *For more details or other ways to [install libraries, visit this link](https://www.arduino.cc/en/Guide/Libraries)
31 |
32 | *For the LED matrix, you will need the [Adafruit LED Backpack library and all the dependencies](https://github.com/adafruit/Adafruit_LED_Backpack/archive/refs/heads/master.zip) just do the exact same installation steps.
33 |
34 | *For the OLED display, you will need the [U8g2 libraries](https://github.com/olikraus/u8g2/archive/refs/heads/master.zip)
35 |
36 | ## Uploading:
37 |
38 | For the firmware code to remote control Ninja via the [Remote XY mobile App](https://remotexy.com), select NodeMCU 1.0 as the board.
39 |
40 | 1. Connect the ESP board using the USB cable to your computer.
41 |
42 | 2. [Upload this code](https://github.com/OttoDIY/OttoNinja/blob/master/examples/App/OttoNinja_APP/OttoNinja_APP.ino)
43 | 3. [Download the app to your phone](https://remotexy.com/en/download/)
44 | 4. Open the app and press + Add new device.
45 | 5. Select the WiFi point.
46 | 6. Select "OTTO NINJA" from the options.
47 | 7. The password is 12345678.
48 |
49 | (Make sure to have wifi disconnected from other networks) and power the robot with a battery all the time.
50 |
51 | ## How to Contribute:
52 | Contributing to this software is warmly welcomed.
53 | 1. Test it, and if you find any problems, then post an issue.
54 | 2. Help us solve the issues or other bugs.
55 | 3. Improve and optimize the current libraries.
56 | You can do this [basically by forking](https://help.github.com/en/articles/fork-a-repo), committing modifications, and then [pull a request](https://help.github.com/en/articles/about-pull-requests).
57 |
58 | Thanks for your contribution, and welcome to the [Otto DIY community](https://www.ottodiy.com/community)
59 |
60 | ## License: CC-BY-SA
61 | You can use all resources of Otto for free, but Otto DIY website must be included in any redistribution, and remixes must keep the CC-BY-SA license. In open source, the idea is that more people can have access; therefore, if you copy or remix Otto, you must also release it under the same open license, which means you must also release all files to the public.
62 |
63 | 
Otto DIY by [www.ottodiy.com](http://www.ottodiy.com) is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
64 |
65 | Thanks to [Sebastian Coddington](https://github.com/SebastianCoddington) for this project.
66 |
--------------------------------------------------------------------------------
/examples/App/OttoNinja_APP/OttoNinja_APP.ino:
--------------------------------------------------------------------------------
1 | // PINOUT FOR ESP8266
2 |
3 | // A0 = GPIO A0 TX = GPIO 1
4 | // D0 = GPIO 16 RX = GPIO 3
5 | // D5 = GPIO 14 D1 = GPIO 5
6 | // D6 = GPIO 12 D2 = GPIO 4
7 | // D7 = GPIO 13 D3 = GPIO 0
8 | // D8 = GPIO 15 D4 = GPIO 2
9 | // S3 = GPIO 9
10 | // SK = GPIO 10
11 |
12 | /*
13 | -- Remote Control Otto Ninja --
14 |
15 | This source code of graphical user interface
16 | has been generated automatically by RemoteXY editor.
17 | To compile this code using RemoteXY library 2.4.3 or later version
18 | download by link http://remotexy.com/en/library/
19 | To connect using RemoteXY mobile app by link http://remotexy.com/en/download/
20 | - for ANDROID 4.5.1 or later version;
21 | - for iOS 1.4.1 or later version;
22 |
23 | This source code is free software; you can redistribute it and/or
24 | modify it under the terms of the GNU Lesser General Public
25 | License as published by the Free Software Foundation; either
26 | version 2.1 of the License, or (at your option) any later version.
27 | */
28 |
29 | //////////////////////////////////////////////
30 | // RemoteXY include library //
31 | //////////////////////////////////////////////
32 |
33 | // RemoteXY select connection mode and include library
34 | #define REMOTEXY_MODE__ESP8266WIFI_LIB_POINT
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 | // RemoteXY connection settings
42 | #define REMOTEXY_WIFI_SSID "OTTO NINJA"
43 | #define REMOTEXY_WIFI_PASSWORD "12345678"
44 | #define REMOTEXY_SERVER_PORT 6377
45 |
46 | // RemoteXY configurate
47 | #pragma pack(push, 1)
48 | uint8_t RemoteXY_CONF[] =
49 | { 255,6,0,0,0,66,0,13,8,0,
50 | 5,32,3,12,41,41,1,26,31,1,
51 | 3,79,16,16,12,1,31,82,240,159,
52 | 166,190,0,1,3,56,39,18,12,1,
53 | 31,240,159,146,191,0,1,3,79,39,
54 | 17,12,1,31,240,159,166,191,0,1,
55 | 3,56,16,17,12,1,31,76,240,159,
56 | 166,190,0 };
57 |
58 | // this structure defines all the variables and events of your control interface
59 | struct {
60 |
61 | // input variables
62 | int8_t J_x; // =-100..100 x-coordinate joystick position
63 | int8_t J_y; // =-100..100 y-coordinate joystick position
64 | uint8_t button_B; // =1 if button pressed, else =0
65 | uint8_t button_X; // =1 if button pressed, else =0
66 | uint8_t button_Y; // =1 if button pressed, else =0
67 | uint8_t button_A; // =1 if button pressed, else =0
68 |
69 | // other variable
70 | uint8_t connect_flag; // =1 if wire connected, else =0
71 |
72 | } RemoteXY;
73 | #pragma pack(pop)
74 |
75 | /////////////////////////////////////////////
76 | // END RemoteXY include //
77 | /////////////////////////////////////////////
78 |
79 | //CALIBRATION SETTINGS:
80 |
81 | ////////// 2:
82 |
83 | // Left foot forward walking rotation Speed
84 | int LFFWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
85 |
86 | // Right foot forward walking rotation Speed
87 | int RFFWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
88 |
89 | ////////// 3:
90 |
91 | // Left foot Backward walking rotation Speed
92 | int LFBWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
93 |
94 | // Right foot Backward walking rotation Speed
95 | int RFBWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
96 |
97 | ////////// 4:
98 |
99 | // Left Leg standing Position
100 | int LA0= 60; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 60
101 |
102 | // Right Leg standing position
103 | int RA0= 120; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 120
104 |
105 | ////////// 5:
106 |
107 | // Left Leg tilt left walking position
108 | int LATL= 100; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 85 Default HUMANOID = 80
109 |
110 | // Right Leg tilt left walking position
111 | int RATL= 175; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 175 Default HUMANOID = 150
112 |
113 | // Left Leg tilt right walking position
114 | int LATR= 5; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 5 Default HUMANOID = 30
115 |
116 | // Right Leg tilt right walking position
117 | int RATR= 80; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 95 Default HUMANOID = 100
118 |
119 | ////////// 6:
120 |
121 | // Left Leg roll Position
122 | int LA1= 180; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 170
123 |
124 | // Right Leg roll position
125 | int RA1= 0; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 10
126 |
127 |
128 | ////////////////////////////////////////
129 |
130 | int currentmillis1 = 0;
131 | int currentmillis2 = 0;
132 | int currentmillis3 = 0;
133 | // Mode counter for biped/wheel mode
134 | int ModeCounter = 0;
135 |
136 | const uint8_t ServoLeftFootPin = 13; //D7
137 | const uint8_t ServoLeftLegPin = 15; //D8
138 | const uint8_t ServoRightFootPin = 0; //D3
139 | const uint8_t ServoRightLegPin = 2; //D4
140 | const uint8_t ServoLeftArmPin = 16; //D0
141 | const uint8_t ServoRightArmPin = 3; //RX
142 | const uint8_t ServoHeadPin = 1; //TX
143 |
144 | Servo myservoLeftFoot;
145 | Servo myservoLeftLeg;
146 | Servo myservoRightFoot;
147 | Servo myservoRightLeg;
148 |
149 | Servo myservoLeftArm;
150 | Servo myservoRightArm;
151 | Servo myservoHead;
152 |
153 | void setup()
154 | {
155 |
156 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
157 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
158 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
159 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
160 |
161 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
162 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
163 |
164 | myservoHead.attach(ServoHeadPin, 544, 2400);
165 |
166 | myservoHead.write(90);
167 | myservoLeftArm.write(90);
168 | myservoRightArm.write(90);
169 | delay(300);
170 | myservoLeftFoot.write(90);
171 | myservoRightFoot.write(90);
172 | myservoLeftLeg.write(60);
173 | myservoRightLeg.write(120);
174 | delay(300);
175 | myservoLeftArm.write(180);
176 | myservoRightArm.write(0);
177 |
178 | delay(500);
179 |
180 | myservoLeftFoot.detach();
181 | myservoRightFoot.detach();
182 | myservoLeftLeg.detach();
183 | myservoRightLeg.detach();
184 |
185 | myservoLeftArm.detach();
186 | myservoRightArm.detach();
187 |
188 | myservoHead.detach();
189 |
190 | Serial.begin(250000);
191 |
192 | RemoteXY_Init ();
193 | }
194 |
195 | void loop()
196 | {
197 | RemoteXY_Handler ();
198 |
199 | if (RemoteXY.button_X == HIGH)
200 | {
201 | NinjaSetRoll();
202 | ModeCounter = 1;
203 | }
204 | if (RemoteXY.button_Y == HIGH)
205 | {
206 | NinjaSetWalk();
207 | ModeCounter = 0;
208 | }
209 | if (RemoteXY.button_A == HIGH)
210 | {
211 | NinjaLeftArm();
212 | }
213 |
214 | if (RemoteXY.button_A == LOW)
215 | {
216 | NinjaLeftArmDown();
217 | }
218 |
219 | if (RemoteXY.button_B == HIGH)
220 | {
221 | NinjaRightArm();
222 | }
223 |
224 | if (RemoteXY.button_B == LOW)
225 | {
226 | NinjaRightArmDown();
227 | }
228 |
229 | if (ModeCounter == 0)
230 | {
231 | if ((RemoteXY.J_x >= -10)&&(RemoteXY.J_x <= 10)&&(RemoteXY.J_y >= -10)&&(RemoteXY.J_y <= 10))
232 | {
233 | NinjaWalkStop();
234 | }
235 |
236 | if (RemoteXY.J_y > 0)
237 | {
238 | int lt= map(RemoteXY.J_x, 100, -100, 200, 700);
239 | int rt= map(RemoteXY.J_x, 100, -100, 700, 200);
240 | int Interval1 = 250;
241 | int Interval2 = 250 + rt;
242 | int Interval3 = 250 + rt + 250;
243 | int Interval4 = 250 + rt + 250 + lt;
244 | int Interval5 = 250 + rt + 250 + lt + 50;
245 |
246 | if(millis() > currentmillis1 + Interval5)
247 | {
248 | currentmillis1 = millis();
249 | }
250 |
251 |
252 | if(millis() - currentmillis1 <= Interval1)
253 | {
254 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
255 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
256 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
257 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
258 |
259 | myservoLeftLeg.write(LATR);
260 | myservoRightLeg.write(RATR);
261 | }
262 |
263 | if((millis() - currentmillis1 >= Interval1)&&(millis() - currentmillis1 <= Interval2))
264 | {
265 | myservoRightFoot.write(90-RFFWRS);
266 |
267 | }
268 |
269 | if((millis() - currentmillis1 >= Interval2)&&(millis() - currentmillis1 <= Interval3))
270 | {
271 | myservoRightFoot.detach();
272 | myservoLeftLeg.write(LATL);
273 | myservoRightLeg.write(RATL);
274 | }
275 |
276 | if((millis() - currentmillis1 >= Interval3)&&(millis() - currentmillis1 <= Interval4))
277 | {
278 | myservoLeftFoot.write(90+LFFWRS);
279 | }
280 |
281 | if((millis() - currentmillis1 >= Interval4)&&(millis() - currentmillis1 <= Interval5))
282 | {
283 | myservoLeftFoot.detach();
284 | }
285 | }
286 |
287 | if (RemoteXY.J_y < 0)
288 | {
289 |
290 | int lt= map(RemoteXY.J_x, 100, -100, 200, 700);
291 | int rt= map(RemoteXY.J_x, 100, -100, 700, 200);
292 | int Interval1 = 250;
293 | int Interval2 = 250 + rt;
294 | int Interval3 = 250 + rt + 250;
295 | int Interval4 = 250 + rt + 250 + lt;
296 | int Interval5 = 250 + rt + 250 + lt + 50;
297 |
298 | if(millis() > currentmillis1 + Interval5)
299 | {
300 | currentmillis1 = millis();
301 | }
302 |
303 |
304 | if(millis() - currentmillis1 <= Interval1)
305 | {
306 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
307 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
308 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
309 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
310 |
311 | myservoLeftLeg.write(LATR);
312 | myservoRightLeg.write(RATR);
313 | }
314 |
315 | if((millis() - currentmillis1 >= Interval1)&&(millis() - currentmillis1 <= Interval2))
316 | {
317 | myservoRightFoot.write(90+RFBWRS);
318 |
319 | }
320 |
321 | if((millis() - currentmillis1 >= Interval2)&&(millis() - currentmillis1 <= Interval3))
322 | {
323 | myservoRightFoot.detach();
324 | myservoLeftLeg.write(LATL);
325 | myservoRightLeg.write(RATL);
326 | }
327 |
328 | if((millis() - currentmillis1 >= Interval3)&&(millis() - currentmillis1 <= Interval4))
329 | {
330 | myservoLeftFoot.write(90-LFBWRS);
331 | }
332 |
333 | if((millis() - currentmillis1 >= Interval4)&&(millis() - currentmillis1 <= Interval5))
334 | {
335 | myservoLeftFoot.detach();
336 | }
337 | }
338 | }
339 |
340 | if (ModeCounter == 1)
341 | {
342 | if ((RemoteXY.J_x >= -10)&&(RemoteXY.J_x <= 10)&&(RemoteXY.J_y >= -10)&&(RemoteXY.J_y <= 10))
343 | {
344 | NinjaRollStop();
345 | }
346 |
347 | else
348 | {
349 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
350 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
351 |
352 | int LWS= map(RemoteXY.J_y, 100, -100, 135, 45);
353 | int RWS= map(RemoteXY.J_y, 100, -100, 45, 135);
354 | int LWD= map(RemoteXY.J_x, 100, -100, 45, 0);
355 | int RWD= map(RemoteXY.J_x, 100, -100, 0, -45);
356 |
357 | myservoLeftFoot.write(LWS+LWD);
358 | myservoRightFoot.write(RWS+RWD);
359 | }
360 | }
361 |
362 | Serial.print(" X: ");
363 | Serial.print(RemoteXY.J_x);
364 | Serial.print(" Y: ");
365 | Serial.print(RemoteXY.J_y);
366 | Serial.print(" MC: ");
367 | Serial.println(ModeCounter);
368 | }
369 |
370 | void NinjaStop()
371 | {
372 | myservoLeftFoot.detach();
373 | myservoRightFoot.detach();
374 | myservoLeftLeg.detach();
375 | myservoRightLeg.detach();
376 | }
377 |
378 | void NinjaSetWalk()
379 | {
380 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
381 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
382 | myservoLeftArm.write(90);
383 | myservoRightArm.write(90);
384 | delay(200);
385 | myservoLeftArm.detach();
386 | myservoRightArm.detach();
387 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
388 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
389 | myservoLeftLeg.write(LA0);
390 | myservoRightLeg.write(RA0);
391 | delay(300);
392 | myservoLeftLeg.detach();
393 | myservoRightLeg.detach();
394 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
395 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
396 | myservoLeftArm.write(180);
397 | myservoRightArm.write(0);
398 | delay(300);
399 | myservoLeftArm.detach();
400 | myservoRightArm.detach();
401 | }
402 |
403 | void NinjaSetRoll()
404 | {
405 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
406 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
407 | myservoLeftArm.write(90);
408 | myservoRightArm.write(90);
409 | delay(200);
410 | myservoLeftArm.detach();
411 | myservoRightArm.detach();
412 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
413 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
414 | myservoLeftLeg.write(LA1);
415 | myservoRightLeg.write(RA1);
416 | delay(300);
417 | myservoLeftLeg.detach();
418 | myservoRightLeg.detach();
419 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
420 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
421 | myservoLeftArm.write(180);
422 | myservoRightArm.write(0);
423 | delay(300);
424 | myservoLeftArm.detach();
425 | myservoRightArm.detach();
426 | }
427 |
428 | void NinjaWalkStop()
429 | {
430 | myservoLeftFoot.write(90);
431 | myservoRightFoot.write(90);
432 | myservoLeftLeg.write(LA0);
433 | myservoRightLeg.write(RA0);
434 | }
435 |
436 | void NinjaRollStop()
437 | {
438 | myservoLeftFoot.write(90);
439 | myservoRightFoot.write(90);
440 | myservoLeftFoot.detach();
441 | myservoRightFoot.detach();
442 | }
443 |
444 | void NinjaLeftArm()
445 | {
446 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
447 | myservoLeftArm.write(90);
448 | }
449 |
450 | void NinjaRightArm()
451 | {
452 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
453 | myservoRightArm.write(90);
454 | }
455 |
456 | void NinjaLeftArmDown()
457 | {
458 | myservoLeftArm.write(180);
459 | }
460 |
461 | void NinjaRightArmDown()
462 | {
463 | myservoRightArm.write(0);
464 | }
465 |
--------------------------------------------------------------------------------
/examples/App/OttoNinja_App_matrix/OttoNinja_App_matrix.ino:
--------------------------------------------------------------------------------
1 | // PINOUT FOR ESP8266
2 |
3 | // A0 = GPIO A0 TX = GPIO 1
4 | // D0 = GPIO 16 RX = GPIO 3
5 | // D5 = GPIO 14 D1 = GPIO 5
6 | // D6 = GPIO 12 D2 = GPIO 4
7 | // D7 = GPIO 13 D3 = GPIO 0
8 | // D8 = GPIO 15 D4 = GPIO 2
9 | // S3 = GPIO 9
10 | // SK = GPIO 10
11 |
12 | /*
13 | -- remote control car wemos --
14 |
15 | This source code of graphical user interface
16 | has been generated automatically by RemoteXY editor.
17 | To compile this code using RemoteXY library 2.4.3 or later version
18 | download by link http://remotexy.com/en/library/
19 | To connect using RemoteXY mobile app by link http://remotexy.com/en/download/
20 | - for ANDROID 4.5.1 or later version;
21 | - for iOS 1.4.1 or later version;
22 |
23 | This source code is free software; you can redistribute it and/or
24 | modify it under the terms of the GNU Lesser General Public
25 | License as published by the Free Software Foundation; either
26 | version 2.1 of the License, or (at your option) any later version.
27 | */
28 |
29 | //////////////////////////////////////////////
30 | // RemoteXY include library //
31 | //////////////////////////////////////////////
32 |
33 | // RemoteXY select connection mode and include library
34 | #define REMOTEXY_MODE__ESP8266WIFI_LIB_POINT
35 | #include
36 |
37 | #include
38 |
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 |
45 | Adafruit_8x16matrix matrix = Adafruit_8x16matrix();
46 |
47 | // RemoteXY connection settings
48 | #define REMOTEXY_WIFI_SSID "OTTO NINJA"
49 | #define REMOTEXY_WIFI_PASSWORD "12345678"
50 | #define REMOTEXY_SERVER_PORT 6377
51 |
52 |
53 | // RemoteXY configurate
54 | #pragma pack(push, 1)
55 | uint8_t RemoteXY_CONF[] =
56 | { 255,6,0,0,0,66,0,13,8,0,
57 | 5,32,3,12,41,41,1,26,31,1,
58 | 3,79,16,16,12,1,31,82,240,159,
59 | 166,190,0,1,3,56,39,18,12,1,
60 | 31,240,159,146,191,0,1,3,79,39,
61 | 17,12,1,31,240,159,166,191,0,1,
62 | 3,56,16,17,12,1,31,76,240,159,
63 | 166,190,0 };
64 |
65 | // this structure defines all the variables and events of your control interface
66 | struct {
67 |
68 | // input variables
69 | int8_t J_x; // =-100..100 x-coordinate joystick position
70 | int8_t J_y; // =-100..100 y-coordinate joystick position
71 | uint8_t button_B; // =1 if button pressed, else =0
72 | uint8_t button_X; // =1 if button pressed, else =0
73 | uint8_t button_Y; // =1 if button pressed, else =0
74 | uint8_t button_A; // =1 if button pressed, else =0
75 |
76 | // other variable
77 | uint8_t connect_flag; // =1 if wire connected, else =0
78 |
79 | } RemoteXY;
80 | #pragma pack(pop)
81 |
82 | /////////////////////////////////////////////
83 | // END RemoteXY include //
84 | /////////////////////////////////////////////
85 |
86 |
87 |
88 |
89 |
90 | //CALIBRATION SETTINGS:
91 |
92 |
93 |
94 | ////////// 2:
95 |
96 | // Left foot forward walking rotation Speed
97 | int LFFWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
98 |
99 | // Right foot forward walking rotation Speed
100 | int RFFWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
101 |
102 | ////////// 3:
103 |
104 | // Left foot Backward walking rotation Speed
105 | int LFBWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
106 |
107 | // Right foot Backward walking rotation Speed
108 | int RFBWRS= 20; // 0 = Slowest 90 = Fastest Default = 12
109 |
110 | ////////// 4:
111 |
112 | // Left Ankle standing Position
113 | int LA0= 60; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 60
114 |
115 | // Right Ankle standing position
116 | int RA0= 120; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 120
117 |
118 | ////////// 5:
119 |
120 | // Left Ankle tilt left walking position
121 | int LATL= 100; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 85 Default HUMANOID = 80
122 |
123 | // Right Ankle tilt left walking position
124 | int RATL= 175; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 175 Default HUMANOID = 150
125 |
126 | // Left Ankle tilt right walking position
127 | int LATR= 5; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 5 Default HUMANOID = 30
128 |
129 | // Right Ankle tilt right walking position
130 | int RATR= 80; // 0 = Full Tilt Right 180 = Full Tilt Left Default BASIC = 95 Default HUMANOID = 100
131 |
132 | ////////// 6:
133 |
134 | // Left Ankle roll Position
135 | int LA1= 180; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 170
136 |
137 | // Right Ankle roll position
138 | int RA1= 0; // 0 = Full Tilt Right 180 = Full Tilt Left Default = 10
139 |
140 |
141 | ////////////////////////////////////////
142 |
143 |
144 |
145 |
146 | int currentmillis1 = 0;
147 | int currentmillis2 = 0;
148 | int currentmillis3 = 0;
149 |
150 |
151 | // Mode counter for biped/wheel mode
152 | int ModeCounter = 0;
153 |
154 |
155 |
156 |
157 |
158 | const uint8_t ServoLeftFootPin = 13; //D7
159 | const uint8_t ServoLeftAnklePin = 15; //D8
160 | const uint8_t ServoRightFootPin = 0; //D3
161 | const uint8_t ServoRightAnklePin = 2; //D4
162 | const uint8_t ServoLeftArmPin = 16; //D0
163 | const uint8_t ServoRightArmPin = 3; //RX
164 | const uint8_t ServoHeadPin = 1; //TX
165 |
166 | Servo myservoLeftFoot;
167 | Servo myservoLeftAnkle;
168 | Servo myservoRightFoot;
169 | Servo myservoRightAnkle;
170 |
171 | Servo myservoLeftArm;
172 | Servo myservoRightArm;
173 | Servo myservoHead;
174 |
175 |
176 |
177 | void setup()
178 | {
179 |
180 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
181 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
182 | myservoLeftAnkle.attach(ServoLeftAnklePin, 544, 2400);
183 | myservoRightAnkle.attach(ServoRightAnklePin, 544, 2400);
184 |
185 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
186 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
187 |
188 | myservoHead.attach(ServoHeadPin, 544, 2400);
189 |
190 | myservoHead.write(90);
191 | myservoLeftArm.write(90);
192 | myservoRightArm.write(90);
193 | delay(300);
194 | myservoLeftFoot.write(90);
195 | myservoRightFoot.write(90);
196 | myservoLeftAnkle.write(60);
197 | myservoRightAnkle.write(120);
198 | delay(300);
199 | myservoLeftArm.write(180);
200 | myservoRightArm.write(0);
201 |
202 |
203 |
204 | delay(500);
205 |
206 | myservoLeftFoot.detach();
207 | myservoRightFoot.detach();
208 | myservoLeftAnkle.detach();
209 | myservoRightAnkle.detach();
210 |
211 | myservoLeftArm.detach();
212 | myservoRightArm.detach();
213 |
214 | myservoHead.detach();
215 |
216 | Serial.begin(250000);
217 |
218 |
219 |
220 | matrix.begin(0x70); // pass in the address
221 |
222 | matrix.setTextSize(1);
223 | matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
224 | matrix.setTextColor(LED_ON);
225 | matrix.setRotation(1);
226 | for (int8_t x=7; x>=-50; x--)
227 | {
228 | matrix.clear();
229 | matrix.setCursor(x,0);
230 | matrix.print("NINJA");
231 | matrix.writeDisplay();
232 | delay(50);
233 | }
234 |
235 | RemoteXY_Init ();
236 | }
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 | void loop()
245 | {
246 | RemoteXY_Handler ();
247 |
248 | if (RemoteXY.button_X == HIGH)
249 | {
250 | RobotSetRoll();
251 | ModeCounter = 1;
252 | }
253 | if (RemoteXY.button_Y == HIGH)
254 | {
255 | RobotSetWalk();
256 | ModeCounter = 0;
257 | }
258 | if (RemoteXY.button_A == HIGH)
259 | {
260 | RobotLeftArm();
261 | }
262 |
263 |
264 | if (RemoteXY.button_A == LOW)
265 | {
266 | RobotLeftArmDown();
267 | }
268 |
269 |
270 |
271 | if (RemoteXY.button_B == HIGH)
272 | {
273 | RobotRightArm();
274 | }
275 |
276 | if (RemoteXY.button_B == LOW)
277 | {
278 | RobotRightArmDown();
279 | }
280 |
281 |
282 |
283 |
284 |
285 | if (ModeCounter == 0)
286 | {
287 | if ((RemoteXY.J_x >= -10)&&(RemoteXY.J_x <= 10)&&(RemoteXY.J_y >= -10)&&(RemoteXY.J_y <= 10))
288 | {
289 | RobotWalkStop();
290 | }
291 |
292 | if (RemoteXY.J_y > 0)
293 | {
294 | int lt= map(RemoteXY.J_x, 100, -100, 200, 700);
295 | int rt= map(RemoteXY.J_x, 100, -100, 700, 200);
296 | int Interval1 = 250;
297 | int Interval2 = 250 + rt;
298 | int Interval3 = 250 + rt + 250;
299 | int Interval4 = 250 + rt + 250 + lt;
300 | int Interval5 = 250 + rt + 250 + lt + 50;
301 |
302 | if(millis() > currentmillis1 + Interval5)
303 | {
304 | currentmillis1 = millis();
305 | }
306 |
307 |
308 | if(millis() - currentmillis1 <= Interval1)
309 | {
310 | myservoLeftAnkle.attach(ServoLeftAnklePin, 544, 2400);
311 | myservoRightAnkle.attach(ServoRightAnklePin, 544, 2400);
312 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
313 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
314 |
315 | myservoLeftAnkle.write(LATR);
316 | myservoRightAnkle.write(RATR);
317 | }
318 |
319 | if((millis() - currentmillis1 >= Interval1)&&(millis() - currentmillis1 <= Interval2))
320 | {
321 | myservoRightFoot.write(90-RFFWRS);
322 |
323 | }
324 |
325 | if((millis() - currentmillis1 >= Interval2)&&(millis() - currentmillis1 <= Interval3))
326 | {
327 | myservoRightFoot.detach();
328 | myservoLeftAnkle.write(LATL);
329 | myservoRightAnkle.write(RATL);
330 | }
331 |
332 | if((millis() - currentmillis1 >= Interval3)&&(millis() - currentmillis1 <= Interval4))
333 | {
334 | myservoLeftFoot.write(90+LFFWRS);
335 | }
336 |
337 | if((millis() - currentmillis1 >= Interval4)&&(millis() - currentmillis1 <= Interval5))
338 | {
339 | myservoLeftFoot.detach();
340 | }
341 |
342 |
343 | }
344 |
345 |
346 | if (RemoteXY.J_y < 0)
347 | {
348 |
349 | int lt= map(RemoteXY.J_x, 100, -100, 200, 700);
350 | int rt= map(RemoteXY.J_x, 100, -100, 700, 200);
351 | int Interval1 = 250;
352 | int Interval2 = 250 + rt;
353 | int Interval3 = 250 + rt + 250;
354 | int Interval4 = 250 + rt + 250 + lt;
355 | int Interval5 = 250 + rt + 250 + lt + 50;
356 |
357 | if(millis() > currentmillis1 + Interval5)
358 | {
359 | currentmillis1 = millis();
360 | }
361 |
362 |
363 | if(millis() - currentmillis1 <= Interval1)
364 | {
365 | myservoLeftAnkle.attach(ServoLeftAnklePin, 544, 2400);
366 | myservoRightAnkle.attach(ServoRightAnklePin, 544, 2400);
367 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
368 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
369 |
370 | myservoLeftAnkle.write(LATR);
371 | myservoRightAnkle.write(RATR);
372 | }
373 |
374 | if((millis() - currentmillis1 >= Interval1)&&(millis() - currentmillis1 <= Interval2))
375 | {
376 | myservoRightFoot.write(90+RFBWRS);
377 |
378 | }
379 |
380 | if((millis() - currentmillis1 >= Interval2)&&(millis() - currentmillis1 <= Interval3))
381 | {
382 | myservoRightFoot.detach();
383 | myservoLeftAnkle.write(LATL);
384 | myservoRightAnkle.write(RATL);
385 | }
386 |
387 | if((millis() - currentmillis1 >= Interval3)&&(millis() - currentmillis1 <= Interval4))
388 | {
389 | myservoLeftFoot.write(90-LFBWRS);
390 | }
391 |
392 | if((millis() - currentmillis1 >= Interval4)&&(millis() - currentmillis1 <= Interval5))
393 | {
394 | myservoLeftFoot.detach();
395 | }
396 |
397 |
398 | }
399 | }
400 |
401 |
402 |
403 |
404 | if (ModeCounter == 1)
405 | {
406 | if ((RemoteXY.J_x >= -10)&&(RemoteXY.J_x <= 10)&&(RemoteXY.J_y >= -10)&&(RemoteXY.J_y <= 10))
407 | {
408 | RobotRollStop();
409 | }
410 |
411 | else
412 | {
413 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
414 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
415 |
416 | int LWS= map(RemoteXY.J_y, 100, -100, 135, 45);
417 | int RWS= map(RemoteXY.J_y, 100, -100, 45, 135);
418 | int LWD= map(RemoteXY.J_x, 100, -100, 45, 0);
419 | int RWD= map(RemoteXY.J_x, 100, -100, 0, -45);
420 |
421 | myservoLeftFoot.write(LWS+LWD);
422 | myservoRightFoot.write(RWS+RWD);
423 | }
424 | }
425 |
426 |
427 |
428 |
429 |
430 |
431 | Serial.print(" X: ");
432 | Serial.print(RemoteXY.J_x);
433 | Serial.print(" Y: ");
434 | Serial.print(RemoteXY.J_y);
435 | Serial.print(" MC: ");
436 | Serial.println(ModeCounter);
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 | }
446 |
447 |
448 |
449 | void RobotStop()
450 | {
451 | myservoLeftFoot.detach();
452 | myservoRightFoot.detach();
453 | myservoLeftAnkle.detach();
454 | myservoRightAnkle.detach();
455 |
456 | }
457 |
458 |
459 | void RobotSetWalk()
460 | {
461 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
462 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
463 | myservoLeftArm.write(90);
464 | myservoRightArm.write(90);
465 | delay(200);
466 | myservoLeftArm.detach();
467 | myservoRightArm.detach();
468 |
469 | myservoLeftAnkle.attach(ServoLeftAnklePin, 544, 2400);
470 | myservoRightAnkle.attach(ServoRightAnklePin, 544, 2400);
471 | myservoLeftAnkle.write(LA0);
472 | myservoRightAnkle.write(RA0);
473 | delay(300);
474 | myservoLeftAnkle.detach();
475 | myservoRightAnkle.detach();
476 |
477 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
478 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
479 | myservoLeftArm.write(180);
480 | myservoRightArm.write(0);
481 | myservoLeftArm.detach();
482 | myservoRightArm.detach();
483 | }
484 |
485 |
486 | void RobotSetRoll()
487 | {
488 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
489 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
490 | myservoLeftArm.write(90);
491 | myservoRightArm.write(90);
492 | delay(200);
493 | myservoLeftArm.detach();
494 | myservoRightArm.detach();
495 | myservoLeftAnkle.attach(ServoLeftAnklePin, 544, 2400);
496 | myservoRightAnkle.attach(ServoRightAnklePin, 544, 2400);
497 | myservoLeftAnkle.write(LA1);
498 | myservoRightAnkle.write(RA1);
499 | delay(300);
500 | myservoLeftAnkle.detach();
501 | myservoRightAnkle.detach();
502 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
503 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
504 | myservoLeftArm.write(180);
505 | myservoRightArm.write(0);
506 | myservoLeftArm.detach();
507 | myservoRightArm.detach();
508 |
509 |
510 |
511 | }
512 |
513 |
514 |
515 | void RobotWalkStop()
516 | {
517 | myservoLeftFoot.write(90);
518 | myservoRightFoot.write(90);
519 | myservoLeftAnkle.write(LA0);
520 | myservoRightAnkle.write(RA0);
521 |
522 | }
523 |
524 |
525 |
526 | void RobotRollStop()
527 | {
528 | myservoLeftFoot.write(90);
529 | myservoRightFoot.write(90);
530 | myservoLeftFoot.detach();
531 | myservoRightFoot.detach();
532 | }
533 |
534 |
535 |
536 |
537 | void RobotLeftArm()
538 | {
539 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
540 | myservoLeftArm.write(90);
541 | }
542 |
543 |
544 |
545 |
546 | void RobotRightArm()
547 | {
548 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
549 | myservoRightArm.write(90);
550 | }
551 |
552 |
553 |
554 | void RobotLeftArmDown()
555 | {
556 | myservoLeftArm.write(180);
557 | }
558 |
559 |
560 |
561 |
562 | void RobotRightArmDown()
563 | {
564 | myservoRightArm.write(0);
565 | }
566 |
--------------------------------------------------------------------------------
/examples/Humanoid/OttoNinjaHumanoid_Avoid/OttoNinjaHumanoid_Avoid.ino:
--------------------------------------------------------------------------------
1 | // PINOUT FOR ESP8266
2 |
3 | // A0 = GPIO A0 TX = GPIO 1
4 | // D0 = GPIO 16 RX = GPIO 3
5 | // D5 = GPIO 14 D1 = GPIO 5
6 | // D6 = GPIO 12 D2 = GPIO 4
7 | // D7 = GPIO 13 D3 = GPIO 0
8 | // D8 = GPIO 15 D4 = GPIO 2
9 | // S3 = GPIO 9
10 | // S2 = GPIO 10
11 |
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | Adafruit_8x16matrix matrix = Adafruit_8x16matrix();
20 |
21 | //CALIBRATION SETTINGS:
22 |
23 | int LA0= 60 +0; // Left Leg standing Position - = Tilt Right + = Tilt Left
24 | int RA0= 120 +0; // Right Leg standing position - = Tilt Right + = Tilt Left
25 | int LA1= 180; // Left Leg roll Position - = Tilt Right + = Tilt Left
26 | int RA1= 0; // Right Leg roll position - = Tilt Right + = Tilt Left
27 | int LATL= LA0 +40; // Left Leg tilt left walking position - = Tilt Right + = Tilt Left
28 | int RATL= RA0 +60; // Right Leg tilt left walking position - = Tilt Right + = Tilt Left
29 | int LATR= LA0 -60; // Left Leg tilt right walking position - = Tilt Right + = Tilt Left
30 | int RATR= RA0 -40; // Right Leg tilt right walking position - = Tilt Right + = Tilt Left
31 |
32 | int LFFWRS=15; // Left foot forward walking rotation Speed 0 = SLOW 90 = FAST
33 | int RFFWRS=15 ; // Right foot forward walking rotation Speed 0 = SLOW 90 = FAST
34 | int LFBWRS= 15; // Left foot Backward walking rotation Speed 0 = SLOW 90 = FAST
35 | int RFBWRS= 15; // Right foot Backward walking rotation Speed 0 = SLOW 90 = FAST
36 |
37 | int LFFRRS=20; // Left foot forward rolling rotation Speed 0 = SLOW 90 = FAST
38 | int RFFRRS=20 ; // Right foot forward rolling rotation Speed 0 = SLOW 90 = FAST
39 | int LFBRRS= 20; // Left foot Backward rolling rotation Speed 0 = SLOW 90 = FAST
40 | int RFBRRS= 20; // Right foot Backward rolling rotation Speed 0 = SLOW 90 = FAST
41 |
42 | ////////////////////////////////////////
43 |
44 |
45 |
46 | int currentmillis1 = 0;
47 |
48 | int Interval1 = 300;
49 | int Interval2 = 600;
50 | int Interval3 = 900;
51 | int Interval4 = 1200;
52 |
53 |
54 | #define echoPin 14 // attach pin D5 ESP8266 to pin Echo of HC-SR04
55 | #define trigPin 12 //attach pin D6 ESP8266 to pin Trig of HC-SR04
56 | long duration; // variable for the duration of sound wave travel
57 | int distance; // variable for the distance measurement
58 |
59 |
60 | const uint8_t ServoLeftFootPin = 13; //D7
61 | const uint8_t ServoLeftLegPin = 15; //D8
62 | const uint8_t ServoRightFootPin = 0; //D3
63 | const uint8_t ServoRightLegPin = 2; //D4
64 | const uint8_t ServoLeftArmPin = 16; //D0
65 | const uint8_t ServoRightArmPin = 3; //RX
66 | const uint8_t ServoHeadPin = 1; //TX
67 |
68 | Servo myservoLeftFoot;
69 | Servo myservoLeftLeg;
70 | Servo myservoRightFoot;
71 | Servo myservoRightLeg;
72 |
73 | Servo myservoLeftArm;
74 | Servo myservoRightArm;
75 | Servo myservoHead;
76 |
77 | void setup()
78 | {
79 |
80 | NinjaHome();
81 |
82 | Serial.begin(250000);
83 |
84 | pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
85 | pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
86 |
87 |
88 | matrix.begin(0x70); // pass in the address
89 |
90 | matrix.setTextSize(1);
91 | matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
92 | matrix.setTextColor(LED_ON);
93 | matrix.setRotation(3);
94 | for (int8_t x=7; x>=-50; x--)
95 | {
96 | matrix.clear();
97 | matrix.setCursor(x,0);
98 | matrix.print("NINJA");
99 | matrix.writeDisplay();
100 | delay(50);
101 | }
102 |
103 | NinjaSetRoll();
104 |
105 | }
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | void loop()
114 | {
115 |
116 | Distance();
117 |
118 |
119 | if (distance >= 15)
120 | {
121 | NinjaRollForward();
122 | HeadScan();
123 | }
124 |
125 | if ((distance >= 2)&&(distance < 15))
126 | {
127 | NinjaRollStop();
128 | myservoHead.attach(ServoHeadPin, 544, 2400);
129 | myservoHead.write(90);
130 | delay(300);
131 | NinjaArmWave();
132 | NinjaRollLeft();
133 | delay(500);
134 | NinjaRollStop();
135 | }
136 |
137 | }
138 |
139 | void NinjaHome()
140 | {
141 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
142 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
143 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
144 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
145 | myservoHead.attach(ServoHeadPin, 544, 2400);
146 | myservoLeftArm.write(180);
147 | myservoRightArm.write(0);
148 | myservoHead.write(90);
149 | delay(400);
150 | myservoLeftFoot.write(90);
151 | myservoRightFoot.write(90);
152 | myservoLeftLeg.write(60);
153 | myservoRightLeg.write(120);
154 | delay(400);
155 | myservoLeftLeg.detach();
156 | myservoRightLeg.detach();
157 | myservoLeftArm.detach();
158 | myservoRightArm.detach();
159 | myservoHead.detach();
160 | }
161 |
162 |
163 |
164 | void NinjaSetWalk()
165 | {
166 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
167 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
168 | myservoLeftArm.write(90);
169 | myservoRightArm.write(90);
170 | delay(200);
171 | myservoLeftArm.detach();
172 | myservoRightArm.detach();
173 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
174 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
175 | myservoLeftLeg.write(LA0);
176 | myservoRightLeg.write(RA0);
177 | delay(300);
178 | myservoLeftLeg.detach();
179 | myservoRightLeg.detach();
180 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
181 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
182 | myservoLeftArm.write(180);
183 | myservoRightArm.write(0);
184 | delay(200);
185 | myservoLeftArm.detach();
186 | myservoRightArm.detach();
187 | }
188 |
189 | void NinjaWalkForward()
190 | {
191 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
192 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
193 |
194 | myservoLeftLeg.write(LATR);
195 | myservoRightLeg.write(RATR);
196 | delay(300);
197 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
198 | myservoRightFoot.write(90-RFFWRS);
199 | delay(300);
200 | myservoRightFoot.detach();
201 | delay(100);
202 | myservoLeftLeg.write(LATL);
203 | myservoRightLeg.write(RATL);
204 | delay(300);
205 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
206 | myservoLeftFoot.write(90+LFFWRS);
207 | delay(300);
208 | myservoLeftFoot.detach();
209 | delay(100);
210 | }
211 |
212 | void NinjaWalkBackward()
213 | {
214 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
215 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
216 |
217 | myservoLeftLeg.write(LATR);
218 | myservoRightLeg.write(RATR);
219 | delay(300);
220 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
221 | myservoRightFoot.write(90+RFBWRS);
222 | delay(300);
223 | myservoRightFoot.detach();
224 | delay(100);
225 | myservoLeftLeg.write(LATL);
226 | myservoRightLeg.write(RATL);
227 | delay(300);
228 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
229 | myservoLeftFoot.write(90-LFBWRS);
230 | delay(300);
231 | myservoLeftFoot.detach();
232 | delay(100);
233 | }
234 |
235 | void NinjaWalkLeft()
236 | {
237 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
238 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
239 |
240 | myservoLeftLeg.write(LATR);
241 | myservoRightLeg.write(RATR);
242 | delay(300);
243 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
244 | myservoRightFoot.write(90-RFFWRS);
245 | delay(50);
246 | myservoRightFoot.detach();
247 | delay(100);
248 | myservoLeftLeg.write(LATL);
249 | myservoRightLeg.write(RATL);
250 | delay(300);
251 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
252 | myservoLeftFoot.write(90+LFFWRS);
253 | delay(300);
254 | myservoLeftFoot.detach();
255 | delay(100);
256 | }
257 |
258 | void NinjaWalkRight()
259 | {
260 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
261 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
262 |
263 | myservoLeftLeg.write(LATR);
264 | myservoRightLeg.write(RATR);
265 | delay(300);
266 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
267 | myservoRightFoot.write(90-RFFWRS);
268 | delay(300);
269 | myservoRightFoot.detach();
270 | delay(100);
271 | myservoLeftLeg.write(LATL);
272 | myservoRightLeg.write(RATL);
273 | delay(300);
274 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
275 | myservoLeftFoot.write(90+LFFWRS);
276 | delay(50);
277 | myservoLeftFoot.detach();
278 | delay(100);
279 | }
280 |
281 | void NinjaWalkStop()
282 | {
283 | myservoLeftFoot.write(90);
284 | myservoRightFoot.write(90);
285 | myservoLeftLeg.write(LA0);
286 | myservoRightLeg.write(RA0);
287 | }
288 |
289 | void NinjaSetRoll()
290 | {
291 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
292 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
293 | myservoLeftArm.write(90);
294 | myservoRightArm.write(90);
295 | delay(200);
296 | myservoLeftArm.detach();
297 | myservoRightArm.detach();
298 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
299 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
300 | myservoLeftLeg.write(LA1);
301 | myservoRightLeg.write(RA1);
302 | delay(300);
303 | myservoLeftLeg.detach();
304 | myservoRightLeg.detach();
305 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
306 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
307 | myservoLeftArm.write(180);
308 | myservoRightArm.write(0);
309 | delay(300);
310 | myservoLeftArm.detach();
311 | myservoRightArm.detach();
312 | }
313 |
314 | void NinjaRollForward()
315 | {
316 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
317 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
318 | myservoLeftFoot.write(90+LFFRRS);
319 | myservoRightFoot.write(90-RFFRRS);
320 | }
321 |
322 | void NinjaRollBackward()
323 | {
324 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
325 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
326 | myservoLeftFoot.write(90-LFBRRS);
327 | myservoRightFoot.write(90+RFBRRS);
328 | }
329 |
330 | void NinjaRollLeft()
331 | {
332 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
333 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
334 | myservoLeftFoot.write(90-LFBRRS);
335 | myservoRightFoot.write(90-RFFRRS);
336 | }
337 |
338 | void NinjaRollRight()
339 | {
340 | myservoLeftFoot.attach(ServoLeftFootPin, 544, 2400);
341 | myservoRightFoot.attach(ServoRightFootPin, 544, 2400);
342 | myservoLeftFoot.write(90+LFFRRS);
343 | myservoRightFoot.write(90+RFBRRS);
344 | }
345 |
346 | void NinjaRollStop()
347 | {
348 | myservoLeftFoot.write(90);
349 | myservoRightFoot.write(90);
350 | myservoLeftFoot.detach();
351 | myservoRightFoot.detach();
352 | }
353 |
354 |
355 |
356 | void NinjaArmWave()
357 | {
358 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
359 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
360 | myservoLeftArm.write(0);
361 | myservoRightArm.write(180);
362 | delay(400);
363 | myservoLeftArm.write(0);
364 | myservoRightArm.write(135);
365 | delay(200);
366 | myservoLeftArm.write(45);
367 | myservoRightArm.write(180);
368 | delay(200);
369 | myservoLeftArm.write(0);
370 | myservoRightArm.write(135);
371 | delay(200);
372 | myservoLeftArm.write(45);
373 | myservoRightArm.write(180);
374 | delay(200);
375 | myservoLeftArm.write(180);
376 | myservoRightArm.write(0);
377 | delay(400);
378 | myservoLeftArm.detach();
379 | myservoRightArm.detach();
380 | }
381 |
382 |
383 |
384 |
385 |
386 | void Distance()
387 | {
388 | // Clears the trigPin condition
389 | digitalWrite(trigPin, LOW);
390 | delayMicroseconds(2);
391 | // Sets the trigPin HIGH (ACTIVE) for 10 microseconds
392 | digitalWrite(trigPin, HIGH);
393 | delayMicroseconds(10);
394 | digitalWrite(trigPin, LOW);
395 | // Reads the echoPin, returns the sound wave travel time in microseconds
396 | duration = pulseIn(echoPin, HIGH);
397 | // Calculating the distance
398 | distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
399 | // Displays the distance on the Serial Monitor
400 | Serial.print("Distance: ");
401 | Serial.print(distance);
402 | Serial.println(" cm");
403 | }
404 |
405 |
406 | void HeadScan()
407 | {
408 |
409 | if(millis() > currentmillis1 + Interval4)
410 | {
411 | currentmillis1 = millis();
412 | }
413 |
414 |
415 | if(millis() - currentmillis1 <= Interval1)
416 | {
417 | myservoHead.attach(ServoHeadPin, 544, 2400);
418 | myservoHead.write(30);
419 | }
420 |
421 | if((millis() - currentmillis1 > Interval1)&&(millis() - currentmillis1 <= Interval2))
422 | {
423 | myservoHead.attach(ServoHeadPin, 544, 2400);
424 | myservoHead.write(90);
425 |
426 | }
427 |
428 | if((millis() - currentmillis1 > Interval2)&&(millis() - currentmillis1 <= Interval3))
429 | {
430 | myservoHead.attach(ServoHeadPin, 544, 2400);
431 | myservoHead.write(150);
432 |
433 | }
434 |
435 | if((millis() - currentmillis1 > Interval3)&&(millis() - currentmillis1 <= Interval4))
436 | {
437 | myservoHead.attach(ServoHeadPin, 544, 2400);
438 | myservoHead.write(90);
439 |
440 | }
441 | }
442 |
--------------------------------------------------------------------------------
/examples/Humanoid/OttoNinjaHumanoid_Demo/OttoNinjaHumanoid_Demo.ino:
--------------------------------------------------------------------------------
1 | /*
2 | This sketch uses a combination of ultrasonic sensor and matrix
3 | to enable Ninja humanoid to say hello Iam Ninja when you wave
4 | your hands in front of him.
5 | */
6 |
7 | // PINOUT FOR ESP8266
8 |
9 | // A0 = GPIO A0 TX = GPIO 1
10 | // D0 = GPIO 16 RX = GPIO 3
11 | // D5 = GPIO 14 D1 = GPIO 5
12 | // D6 = GPIO 12 D2 = GPIO 4
13 | // D7 = GPIO 13 D3 = GPIO 0
14 | // D8 = GPIO 15 D4 = GPIO 2
15 | // S3 = GPIO 9
16 | // S2 = GPIO 10
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | Adafruit_8x16matrix matrix = Adafruit_8x16matrix();
26 |
27 | //CALIBRATION SETTINGS:
28 |
29 | int LA0= 60 +0; // Left Leg standing Position - = Tilt Right + = Tilt Left
30 | int RA0= 120 +0; // Right Leg standing position - = Tilt Right + = Tilt Left
31 | int LA1= 180; // Left Leg roll Position - = Tilt Right + = Tilt Left
32 | int RA1= 0; // Right Leg roll position - = Tilt Right + = Tilt Left
33 | int LATL= LA0 +40; // Left Leg tilt left walking position - = Tilt Right + = Tilt Left
34 | int RATL= RA0 +60; // Right Leg tilt left walking position - = Tilt Right + = Tilt Left
35 | int LATR= LA0 -60; // Left Leg tilt right walking position - = Tilt Right + = Tilt Left
36 | int RATR= RA0 -40; // Right Leg tilt right walking position - = Tilt Right + = Tilt Left
37 |
38 | int LFFWRS=15; // Left foot forward walking rotation Speed 0 = SLOW 90 = FAST
39 | int RFFWRS=15 ; // Right foot forward walking rotation Speed 0 = SLOW 90 = FAST
40 | int LFBWRS= 15; // Left foot Backward walking rotation Speed 0 = SLOW 90 = FAST
41 | int RFBWRS= 15; // Right foot Backward walking rotation Speed 0 = SLOW 90 = FAST
42 |
43 |
44 | ////////////////////////////////////////
45 |
46 | const uint8_t ServoLeftFootPin = 13; //D7
47 | const uint8_t ServoLeftLegPin = 15; //D8
48 | const uint8_t ServoRightFootPin = 0; //D3
49 | const uint8_t ServoRightLegPin = 2; //D4
50 | const uint8_t ServoLeftArmPin = 16; //D0
51 | const uint8_t ServoRightArmPin = 3; //RX
52 | const uint8_t ServoHeadPin = 1; //TX
53 |
54 | Servo myservoLeftFoot;
55 | Servo myservoLeftLeg;
56 | Servo myservoRightFoot;
57 | Servo myservoRightLeg;
58 |
59 | Servo myservoLeftArm;
60 | Servo myservoRightArm;
61 | Servo myservoHead;
62 |
63 | #define echoPin 14 // attach pin D5 ESP8266 to pin Echo of HC-SR04
64 | #define trigPin 12 //attach pin D6 ESP8266 to pin Trig of HC-SR04
65 | long duration; // variable for the duration of sound wave travel
66 | int distance; // variable for the distance measurement
67 |
68 | void setup()
69 | {
70 |
71 | NinjaHome();
72 |
73 | Serial.begin(250000);
74 |
75 | pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
76 | pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
77 |
78 | matrix.begin(0x70); // pass in the address
79 |
80 | matrix.setTextSize(1);
81 | matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
82 | matrix.setTextColor(LED_ON);
83 | matrix.setRotation(3);
84 | for (int8_t x=7; x>=-50; x--)
85 | {
86 | matrix.clear();
87 | matrix.setCursor(x,0);
88 | matrix.print("NINJA");
89 | matrix.writeDisplay();
90 | delay(50);
91 | }
92 |
93 | }
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | void loop()
102 | {
103 |
104 | Distance();
105 |
106 | if ((distance >= 2)&&(distance < 10))
107 | {
108 | RobotHeadShake();
109 | RobotLeftArmWave();
110 | IAmNinja();
111 | }
112 |
113 | }
114 |
115 |
116 | void NinjaHome()
117 | {
118 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
119 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
120 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
121 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
122 | myservoHead.attach(ServoHeadPin, 544, 2400);
123 | myservoLeftArm.write(180);
124 | myservoRightArm.write(0);
125 | myservoHead.write(90);
126 | delay(400);
127 | myservoLeftLeg.write(60);
128 | myservoRightLeg.write(120);
129 | delay(400);
130 | myservoLeftLeg.detach();
131 | myservoRightLeg.detach();
132 | myservoLeftArm.detach();
133 | myservoRightArm.detach();
134 | myservoHead.detach();
135 | }
136 |
137 |
138 | void RobotHeadShake()
139 | {
140 | myservoHead.attach(ServoHeadPin, 544, 2400);
141 | myservoHead.write(135);
142 | delay(200);
143 | myservoHead.write(45);
144 | delay(400);
145 | myservoHead.write(90);
146 | delay(200);
147 |
148 | }
149 |
150 |
151 | void RobotLeftArmWave()
152 | {
153 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
154 | myservoRightArm.write(180);
155 | delay(400);
156 | myservoRightArm.write(135);
157 | delay(200);
158 | myservoRightArm.write(180);
159 | delay(200);
160 | myservoRightArm.write(135);
161 | delay(200);
162 | myservoRightArm.write(180);
163 | delay(200);
164 | myservoRightArm.write(0);
165 | delay(400);
166 | }
167 |
168 |
169 |
170 | void IAmNinja()
171 | {
172 | matrix.setTextSize(1);
173 | matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
174 | matrix.setTextColor(LED_ON);
175 | matrix.setRotation(3);
176 | for (int8_t x=7; x>=-80; x--)
177 | {
178 | matrix.clear();
179 | matrix.setCursor(x,0);
180 | matrix.print("I AM NINJA");
181 | matrix.writeDisplay();
182 | delay(50);
183 | }
184 | }
185 |
186 | void Distance()
187 | {
188 | // Clears the trigPin condition
189 | digitalWrite(trigPin, LOW);
190 | delayMicroseconds(2);
191 | // Sets the trigPin HIGH (ACTIVE) for 10 microseconds
192 | digitalWrite(trigPin, HIGH);
193 | delayMicroseconds(10);
194 | digitalWrite(trigPin, LOW);
195 | // Reads the echoPin, returns the sound wave travel time in microseconds
196 | duration = pulseIn(echoPin, HIGH);
197 | // Calculating the distance
198 | distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
199 | // Displays the distance on the Serial Monitor
200 | Serial.print("Distance: ");
201 | Serial.print(distance);
202 | Serial.println(" cm");
203 | }
204 |
--------------------------------------------------------------------------------
/examples/LED matrix/OttoE_alleyes/OttoE_alleyes.ino:
--------------------------------------------------------------------------------
1 | /***************************************************
2 | Designed specifically to work with the Otto DIY 16x8 LED Matrix eyes
3 |
4 | These display use I2C to communicate, 2 pins are required to
5 | interface. There are multiple selectable I2C addresses. For
6 | with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
7 | with 3 Address Select pins: 0x70 thru 0x77
8 |
9 | Otto DIY invests time and resources providing this open source code,
10 | please support Otto DIY and open-source hardware by purchasing
11 | products from ottodiy.com!
12 | ****************************************************/
13 |
14 | #include
15 | #include
16 | Adafruit_8x16matrix matrix = Adafruit_8x16matrix();
17 |
18 | static const uint8_t PROGMEM
19 | logo_bmp[] = { B01111110,B10000001,B10111001,B10101001,B10111001,B10010001,B10111001,B10010001,B10010001,B10111001,B10010001,B10111001,B10101001,B10111001,B10000001,B01111110},
20 | happy_bmp[] = { B00000000,B00111100,B00000010,B00000010,B00000010,B00000010,B00111100,B00000000,B00000000,B00111100,B00000010,B00000010,B00000010,B00000010,B00111100,B00000000},
21 | eyes_bmp[] = { B00000000,B00111100,B01000010,B01001010,B01000010,B01000010,B00111100,B00000000,B00000000,B00111100,B01000010,B01001010,B01000010,B01000010,B00111100,B00000000},
22 | sad_bmp[] = { B00000000,B00010000,B00010000,B00010000,B00010000,B00010000,B00010000,B00000000,B00000000,B00010000,B00010000,B00010000,B00010000,B00010000,B00010000,B00000000},
23 | xx_bmp[] = { B00000000,B00100010,B00010100,B00001000,B00010100,B00100010,B00000000,B00000000,B00000000,B00000000,B00100010,B00010100,B00001000,B00010100,B00100010,B00000000},
24 | XX_bmp[] = { B01000001,B00100010,B00010100,B00001000,B00010100,B00100010,B01000001,B00000000,B00000000,B01000001,B00100010,B00010100,B00001000,B00010100,B00100010,B01000001},
25 | angry_bmp[] = { B00000000,B00011110,B00111100,B01111000,B01110000,B00100000,B00000000,B00000000,B00000000,B00000000,B00100000,B01110000,B01111000,B00111100,B00011110,B00000000},
26 | angry2_bmp[] = { B00000000,B00000010,B00000100,B00001000,B00010000,B00100000,B00000000,B00000000,B00000000,B00000000,B00100000,B00010000,B00001000,B00000100,B00000010,B00000000},
27 | sleep_bmp[] = { B00000000,B00100010,B00110010,B00101010,B00100110,B00100010,B00000000,B00000000,B00000000,B00000000,B00100010,B00110010,B00101010,B00100110,B00100010,B00000000},
28 | freetful_bmp[] = { B00000000,B00100000,B00010000,B00001000,B00000100,B00000010,B00000000,B00000000,B00000000,B00000000,B00000010,B00000100,B00001000,B00010000,B00100000,B00000000},
29 | love_bmp[] = { B00000000,B00001100,B00011110,B00111100,B00111100,B00011110,B00001100,B00000000,B00000000,B00001100,B00011110,B00111100,B00111100,B00011110,B00001100,B00000000},
30 | confused_bmp[] = { B00000000,B01111100,B10000010,B10111010,B10101010,B10001010,B01111000,B00000000,B00000000,B01111100,B10000010,B10111010,B10101010,B10001010,B01111000,B00000000},
31 | wave_bmp[] = { B00000000,B00100000,B00010000,B00001000,B00010000,B00100000,B00010000,B00000000,B00000000,B00100000,B00010000,B00001000,B00010000,B00100000,B00010000,B00000000},
32 | magic_bmp[] = { B00000000,B00000000,B01111110,B11111111,B01111110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01111110,B11111111,B01111110,B00000000,B00000000},
33 | fail_bmp[] = { B00000000,B00110000,B01111000,B01111000,B01111100,B00111100,B00001000,B00000000,B00000000,B00001000,B00111100,B01111100,B01111000,B01111000,B00110000,B00000000},
34 | full_bmp[] = { B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111 };
35 |
36 | void setup() {
37 | Serial.begin(9600);
38 | Serial.println("16x8 LED Matrix Test");
39 | matrix.begin(0x70); // pass in the address
40 | }
41 |
42 | void loop() {
43 |
44 | matrix.setTextSize(1);
45 | matrix.setTextWrap(true); // we dont want text to wrap so it scrolls nicely
46 | matrix.setTextColor(LED_ON);
47 | matrix.setRotation(1);
48 | for (int8_t x=0; x>=-70; x--) {
49 | matrix.clear();
50 | matrix.setCursor(x,0);
51 | matrix.print("I am a Ninja!");
52 | matrix.writeDisplay();
53 | delay(100);
54 | }
55 | matrix.setRotation(0);
56 |
57 | matrix.clear();
58 | matrix.drawBitmap(0, 8, full_bmp, 8, 8, LED_ON);
59 | matrix.writeDisplay();
60 | delay(1000);
61 |
62 | matrix.clear();
63 | matrix.drawBitmap(0, 0, full_bmp, 8, 8, LED_ON);
64 | matrix.writeDisplay();
65 | delay(1000);
66 | matrix.clear();
67 | matrix.drawBitmap(0, 0, happy_bmp, 8, 16, LED_ON);
68 | matrix.writeDisplay();
69 | delay(2000);
70 | matrix.clear();
71 | matrix.drawBitmap(0, 0, eyes_bmp, 8, 16, LED_ON);
72 | matrix.writeDisplay();
73 | delay(2000);
74 | matrix.clear();
75 | matrix.drawBitmap(0, 0, sad_bmp, 8, 16, LED_ON);
76 | matrix.writeDisplay();
77 | delay(2000);
78 | matrix.clear();
79 | matrix.drawBitmap(0, 0, angry_bmp, 8, 16, LED_ON);
80 | matrix.writeDisplay();
81 | delay(2000);
82 | matrix.clear();
83 | matrix.drawBitmap(0, 0, sleep_bmp, 8, 16, LED_ON);
84 | matrix.writeDisplay();
85 | delay(2000);
86 | matrix.clear();
87 | matrix.drawBitmap(0, 0, freetful_bmp, 8, 16, LED_ON);
88 | matrix.writeDisplay();
89 | delay(2000);
90 | matrix.clear();
91 | matrix.drawBitmap(0, 0, love_bmp, 8, 16, LED_ON);
92 | matrix.writeDisplay();
93 | delay(2000);
94 | matrix.clear();
95 | matrix.drawBitmap(0, 0, confused_bmp, 8, 16, LED_ON);
96 | matrix.writeDisplay();
97 | delay(2000);
98 | matrix.clear();
99 | matrix.drawBitmap(0, 0, wave_bmp, 8, 16, LED_ON);
100 | matrix.writeDisplay();
101 | delay(2000);
102 | matrix.clear();
103 | matrix.drawBitmap(0, 0, magic_bmp, 8, 16, LED_ON);
104 | matrix.writeDisplay();
105 | delay(2000);
106 | matrix.clear();
107 | matrix.drawBitmap(0, 0, fail_bmp, 8, 16, LED_ON);
108 | matrix.writeDisplay();
109 | delay(500);
110 | matrix.clear();
111 | matrix.drawBitmap(0, 0, xx_bmp, 8, 16, LED_ON);
112 | matrix.writeDisplay();
113 | delay(200);
114 | matrix.clear();
115 | matrix.drawBitmap(0, 0, XX_bmp, 8, 16, LED_ON);
116 | matrix.writeDisplay();
117 | delay(1000);
118 |
119 | matrix.clear();
120 | matrix.drawBitmap(0, 0, logo_bmp, 8, 16, LED_ON);
121 | matrix.writeDisplay();
122 | delay(1000);
123 |
124 | matrix.setTextSize(1);
125 | matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
126 | matrix.setTextColor(LED_ON);
127 | matrix.setRotation(1);
128 | for (int8_t x=7; x>=-36; x--) {
129 | matrix.clear();
130 | matrix.setCursor(x,0);
131 | matrix.print("Otto DIY");
132 | matrix.writeDisplay();
133 | delay(100);
134 | }
135 | matrix.setRotation(0);
136 |
137 | matrix.clear(); // clear display
138 | matrix.drawPixel(0, 0, LED_ON);
139 | matrix.writeDisplay(); // write the changes we just made to the display
140 | delay(500);
141 |
142 | matrix.clear();
143 | matrix.drawLine(0,0, 7,15, LED_ON);
144 | matrix.writeDisplay(); // write the changes we just made to the display
145 | delay(500);
146 |
147 | matrix.clear();
148 | matrix.drawRect(0,0, 8,16, LED_ON);
149 | matrix.fillRect(2,2, 4,12, LED_ON);
150 | matrix.writeDisplay(); // write the changes we just made to the display
151 | delay(500);
152 |
153 | matrix.clear();
154 | matrix.drawCircle(3,8, 3, LED_ON);
155 | matrix.writeDisplay(); // write the changes we just made to the display
156 | delay(500);
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/examples/LED matrix/OttoE_flappybird/OttoE_flappybird.ino:
--------------------------------------------------------------------------------
1 | // Arduino Flappy Bird homage by augustzf@gmail.com
2 | #include
3 | #include
4 | #include
5 | #include
6 | Adafruit_8x16matrix matrix = Adafruit_8x16matrix();
7 |
8 | static const uint8_t PROGMEM
9 | bird0[] =
10 | {
11 | B00011000,
12 | B00111100,
13 | B00110100,
14 | B11111111,
15 | B10111111,
16 | B11011100,
17 | B01111100,
18 | B00111000 }
19 | ,
20 | bird1[] =
21 | {
22 | B00000000,
23 | B00011000,
24 | B00111100,
25 | B00110111,
26 | B11111111,
27 | B10011100,
28 | B11111100,
29 | B00111000 }
30 | ,
31 | bird2[] =
32 | {
33 | B00011000,
34 | B00111100,
35 | B00110100,
36 | B00111111,
37 | B01111111,
38 | B11011100,
39 | B10111100,
40 | B11111000 };
41 |
42 | const byte vibration PROGMEM = A0; // vibration sensor
43 | const int tapLevel PROGMEM = 512;
44 |
45 | double initYVelocity = 6.5;
46 | double gravity = -9.8;
47 | long birdTime;
48 | long previousBirdTime;
49 | byte birdPos = 3;
50 | byte tailPos = 3;
51 | byte birdStart;
52 | byte topWall;
53 | byte bottomWall;
54 | int wallDelay = 250;
55 | byte wallGap = 5;
56 | long wallTime;
57 | int wallCount;
58 | long previousWallTime;
59 | byte wallPosition = 0;
60 | boolean gameMode = false;
61 | long frameTime;
62 | long previousFrameTime;
63 | byte frame = 0;
64 | byte frameChange = 1;
65 | byte lives = 2;
66 |
67 | void setup() {
68 |
69 | pinMode(vibration, INPUT_PULLUP);
70 |
71 | matrix.begin(0x70);
72 | matrix.setRotation(1);
73 | matrix.setBrightness(3);
74 | matrix.setTextSize(1);
75 | matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
76 | matrix.setTextColor(LED_ON);
77 | matrix.clear();
78 | matrix.writeDisplay();
79 | previousBirdTime = millis();
80 | topWall = random(0,4);
81 | bottomWall = topWall + 4;
82 | wallPosition = 0;
83 | gameMode = false;
84 | }
85 |
86 | void loop() {
87 | matrix.clear();
88 |
89 | if(gameMode == false)
90 | {
91 |
92 | if(analogRead(vibration)< tapLevel)
93 | {
94 | gameMode = true;
95 | }
96 |
97 | frameTime = millis();
98 |
99 | if(frameTime - previousFrameTime > 250) {
100 | previousFrameTime = frameTime;
101 | frame += frameChange;
102 | if(frame >= 2 || frame <= 0) frameChange *= -1;
103 | }
104 |
105 | if(frame == 0) matrix.drawBitmap(0, 0, bird0, 8, 8, LED_ON);
106 | else if(frame == 1) matrix.drawBitmap(0, 0, bird1, 8, 8, LED_ON);
107 | else if(frame == 2) matrix.drawBitmap(0, 0, bird2, 8, 8, LED_ON);
108 | }
109 |
110 | else
111 | {
112 | if(analogRead(vibration)= bottomWall || next <= topWall)
125 | {
126 | gameMode = false;
127 |
128 | int scoreInt = wallCount-1;
129 |
130 | const char* temp = "Game Over";
131 |
132 | for (int8_t x=15; x>=-1*9*5+1; x--)
133 | {
134 | matrix.clear();
135 | matrix.setCursor(x,0);
136 | matrix.print(temp);
137 | matrix.writeDisplay();
138 | delay(75);
139 | }
140 | }
141 | wallCount++;
142 | }
143 |
144 | }
145 |
146 | matrix.writeDisplay();
147 | }
148 |
149 | void drawWalls()
150 | {
151 | wallTime = millis();
152 |
153 | if(wallPosition > 15)
154 | {
155 | topWall = random(0,4);
156 | bottomWall = topWall + 4;
157 | wallPosition = 0;
158 | }
159 |
160 | matrix.drawLine(15-wallPosition, 0, 15-wallPosition, topWall, LED_ON);
161 |
162 | matrix.drawLine(15-wallPosition, bottomWall, 15-wallPosition, 15, LED_ON);
163 |
164 | if(wallTime - previousWallTime > wallDelay) {
165 | previousWallTime = wallTime;
166 | wallPosition++;
167 | }
168 | }
169 |
170 | int calculateY()
171 | {
172 | return (int)(birdStart+((birdTime/1000.0)*(initYVelocity+gravity*(birdTime/1000.0)/2.0)));
173 | }
174 |
175 | int calculateTail()
176 | {
177 | return (int)(birdStart+(((birdTime-100)/1000.0)*(initYVelocity+gravity*((birdTime-100)/1000.0)/2.0)));
178 | }
179 |
180 | int calculateNextY()
181 | {
182 | return (int)(birdStart+(((birdTime+100)/1000.0)*(initYVelocity+gravity*((birdTime+100)/1000.0)/2.0)));
183 | }
184 |
185 | void drawBird()
186 | {
187 | birdTime = millis() - previousBirdTime;
188 | birdPos = calculateY();
189 | tailPos = calculateTail();
190 | if(calculateY() < 0) birdPos = 0;
191 | if(calculateTail() < 0) tailPos = 0;
192 | matrix.drawPixel(0, 7-tailPos, LED_ON);
193 | matrix.drawPixel(1, 7-birdPos, LED_ON);
194 | matrix.writeDisplay();
195 | }
196 |
--------------------------------------------------------------------------------
/examples/LED matrix/OttoE_rolleyes/OttoE_rolleyes.ino:
--------------------------------------------------------------------------------
1 | // This sketch demonstrates a couple of useful techniques:
2 | // 1) Addressing multiple matrices (using the 'A0' and 'A1' solder
3 | // pads on the back to select unique I2C addresses for each).
4 | // 2) Displaying the same data on multiple matrices by sharing the
5 | // same I2C address.
6 | //
7 | // This example uses 5 matrices at 4 addresses (two share an address)
8 | // to animate a face:
9 | //
10 | // 0 0
11 | //
12 | // 1 2 3
13 | //
14 | // The 'eyes' both display the same image (always looking the same
15 | // direction -- can't go cross-eyed) and thus share the same address
16 | // (0x70). The three matrices forming the mouth have unique addresses
17 | // (0x71, 0x72 and 0x73).
18 | //
19 | // The face animation as written is here semi-random; this neither
20 | // generates nor responds to actual sound, it's simply a visual effect
21 | // Consider this a stepping off point for your own project. Maybe you
22 | // could 'puppet' the face using joysticks, or synchronize the lips to
23 | // audio from a Wave Shield (see wavface example). Currently there are
24 | // only six images for the mouth. This is often sufficient for simple
25 | // animation, as explained here:
26 | // http://www.idleworm.com/how/anm/03t/talk1.shtml
27 | //
28 | // Adafruit invests time and resources providing this open source code,
29 | // please support Adafruit and open-source hardware by purchasing
30 | // products from Adafruit!
31 | //
32 | // Written by Camilo Parra Palacio for Otto DIY.
33 | // BSD license, all text above must be included in any redistribution.
34 |
35 | #include
36 | #include
37 | #include
38 | #include
39 |
40 | // Because the two eye matrices share the same address, only four
41 | // matrix objects are needed for the five displays:
42 | #define MATRIX_EYES 0
43 | #define MATRIX_MOUTH_LEFT 1
44 | #define MATRIX_MOUTH_MIDDLE 2
45 | #define MATRIX_MOUTH_RIGHT 3
46 | Adafruit_8x16matrix matrix[4] = { // Array of Adafruit_8x16matrix objects
47 | Adafruit_8x16matrix(), Adafruit_8x16matrix(),
48 | Adafruit_8x16matrix(), Adafruit_8x16matrix() };
49 |
50 | // Rather than assigning matrix addresses sequentially in a loop, each
51 | // has a spot in this array. This makes it easier if you inadvertently
52 | // install one or more matrices in the wrong physical position --
53 | // re-order the addresses in this table and you can still refer to
54 | // matrices by index above, no other code or wiring needs to change.
55 | static const uint8_t matrixAddr[] = { 0x70, 0x71, 0x72, 0x73 };
56 |
57 | static const uint8_t PROGMEM // Bitmaps are stored in program memory
58 | blinkImg[][8] = { // Eye animation frames
59 | { B00000000, // Fully open eye
60 | B00111100,
61 | B01111110,
62 | B01111110,
63 | B01111110,
64 | B01111110,
65 | B00111100,
66 | B00000000 },
67 | { B00011000,
68 | B00011000,
69 | B00111110,
70 | B01111110,
71 | B01111110,
72 | B00111110,
73 | B00111100,
74 | B00011000 },
75 | { B00011000,
76 | B00011000,
77 | B00011100,
78 | B00111100,
79 | B00111100,
80 | B00011100,
81 | B00011000,
82 | B00011000 },
83 | { B00001000,
84 | B00011000,
85 | B00001100,
86 | B00001100,
87 | B00001100,
88 | B00001100,
89 | B00011000,
90 | B00001000 },
91 | { B00001000, // Fully closed eye
92 | B00000100,
93 | B00000100,
94 | B00000100,
95 | B00000100,
96 | B00000100,
97 | B00000100,
98 | B00001000 } },
99 | mouthImg[][24] = { // Mouth animation frames
100 | { B00000000, B00000000, B00000000, // Mouth position A
101 | B00000000, B00000000, B00000000,
102 | B01111111, B11111111, B11111110,
103 | B00000000, B00000000, B00000000,
104 | B00000000, B00000000, B00000000,
105 | B00000000, B00000000, B00000000,
106 | B00000000, B00000000, B00000000,
107 | B00000000, B00000000, B00000000 },
108 | { B00000000, B00000000, B00000000, // Mouth position B
109 | B00000000, B00000000, B00000000,
110 | B00111111, B11111111, B11111100,
111 | B00000111, B00000000, B11100000,
112 | B00000000, B11111111, B00000000,
113 | B00000000, B00000000, B00000000,
114 | B00000000, B00000000, B00000000,
115 | B00000000, B00000000, B00000000 },
116 | { B00000000, B00000000, B00000000, // Mouth position C
117 | B00000000, B00000000, B00000000,
118 | B00111111, B11111111, B11111100,
119 | B00001000, B00000000, B00010000,
120 | B00000110, B00000000, B01100000,
121 | B00000001, B11000011, B10000000,
122 | B00000000, B00111100, B00000000,
123 | B00000000, B00000000, B00000000 },
124 | { B00000000, B00000000, B00000000, // Mouth position D
125 | B00000000, B00000000, B00000000,
126 | B00111111, B11111111, B11111100,
127 | B00100000, B00000000, B00000100,
128 | B00010000, B00000000, B00001000,
129 | B00001100, B00000000, B00110000,
130 | B00000011, B10000001, B11000000,
131 | B00000000, B01111110, B00000000 },
132 | { B00000000, B00000000, B00000000, // Mouth position E
133 | B00000000, B00111100, B00000000,
134 | B00011111, B11000011, B11111000,
135 | B00000011, B10000001, B11000000,
136 | B00000000, B01111110, B00000000,
137 | B00000000, B00000000, B00000000,
138 | B00000000, B00000000, B00000000,
139 | B00000000, B00000000, B00000000 },
140 | { B00000000, B00111100, B00000000, // Mouth position F
141 | B00000000, B11000011, B00000000,
142 | B00001111, B00000000, B11110000,
143 | B00000001, B00000000, B10000000,
144 | B00000000, B11000011, B00000000,
145 | B00000000, B00111100, B00000000,
146 | B00000000, B00000000, B00000000,
147 | B00000000, B00000000, B00000000 } };
148 |
149 | uint8_t
150 | blinkIndex[] = { 1, 2, 3, 4, 3, 2, 1 }, // Blink bitmap sequence
151 | blinkCountdown = 100, // Countdown to next blink (in frames)
152 | gazeCountdown = 75, // Countdown to next eye movement
153 | gazeFrames = 50, // Duration of eye movement (smaller = faster)
154 | mouthPos = 0, // Current image number for mouth
155 | mouthCountdown = 10; // Countdown to next mouth change
156 | int8_t
157 | eyeX = 3, eyeY = 3, // Current eye position
158 | newX = 3, newY = 3, // Next eye position
159 | dX = 0, dY = 0; // Distance from prior to new position
160 |
161 | void setup() {
162 |
163 | // Seed random number generator from an unused analog input:
164 | randomSeed(analogRead(A0));
165 |
166 | // Initialize each matrix object:
167 | for(uint8_t i=0; i<4; i++) {
168 | matrix[i].begin(matrixAddr[i]);
169 | // If using 'small' (1.2") displays vs. 'mini' (0.8"), enable this:
170 | // matrix[i].setRotation(3);
171 | }
172 | }
173 |
174 | void loop() {
175 |
176 | // Draw eyeball in current state of blinkyness (no pupil). Note that
177 | // only one eye needs to be drawn. Because the two eye matrices share
178 | // the same address, the same data will be received by both.
179 | matrix[MATRIX_EYES].clear();
180 | // When counting down to the next blink, show the eye in the fully-
181 | // open state. On the last few counts (during the blink), look up
182 | // the corresponding bitmap index.
183 | matrix[MATRIX_EYES].drawBitmap(0, 0,
184 | blinkImg[
185 | (blinkCountdown < sizeof(blinkIndex)) ? // Currently blinking?
186 | blinkIndex[blinkCountdown] : // Yes, look up bitmap #
187 | 0 // No, show bitmap 0
188 | ], 8, 8, LED_ON);
189 | matrix[MATRIX_EYES].drawBitmap(0, 8,
190 | blinkImg[
191 | (blinkCountdown < sizeof(blinkIndex)) ? // Currently blinking?
192 | blinkIndex[blinkCountdown] : // Yes, look up bitmap #
193 | 0 // No, show bitmap 0
194 | ], 8, 8, LED_ON);
195 | // Decrement blink counter. At end, set random time for next blink.
196 | if(--blinkCountdown == 0) blinkCountdown = random(5, 180);
197 |
198 | // Add a pupil (2x2 black square) atop the blinky eyeball bitmap.
199 | // Periodically, the pupil moves to a new position...
200 | if(--gazeCountdown <= gazeFrames) {
201 | // Eyes are in motion - draw pupil at interim position
202 | matrix[MATRIX_EYES].fillRect(
203 | newX - (dX * gazeCountdown / gazeFrames),
204 | newY - (dY * gazeCountdown / gazeFrames),
205 | 2, 2, LED_OFF);
206 | matrix[MATRIX_EYES].fillRect(
207 | newX - (dX * gazeCountdown / gazeFrames),
208 | 8+newY - (dY * gazeCountdown / gazeFrames),
209 | 2, 2, LED_OFF);
210 | if(gazeCountdown == 0) { // Last frame?
211 | eyeX = newX; eyeY = newY; // Yes. What's new is old, then...
212 | do { // Pick random positions until one is within the eye circle
213 | newX = random(7); newY = random(7);
214 | dX = newX - 3; dY = newY - 3;
215 | } while((dX * dX + dY * dY) >= 10); // Thank you Pythagoras
216 | dX = newX - eyeX; // Horizontal distance to move
217 | dY = newY - eyeY; // Vertical distance to move
218 | gazeFrames = random(3, 15); // Duration of eye movement
219 | gazeCountdown = random(gazeFrames, 120); // Count to end of next movement
220 | }
221 | } else {
222 | // Not in motion yet -- draw pupil at current static position
223 | matrix[MATRIX_EYES].fillRect(eyeX, eyeY, 2, 2, LED_OFF);
224 | matrix[MATRIX_EYES].fillRect(eyeX, 8+eyeY, 2, 2, LED_OFF);
225 | }
226 |
227 | // Draw mouth, switch to new random image periodically
228 | drawMouth(mouthImg[mouthPos]);
229 | if(--mouthCountdown == 0) {
230 | mouthPos = random(6); // Random image
231 | // If the 'neutral' position was chosen, there's a 1-in-5 chance we'll
232 | // select a longer hold time. This gives the appearance of periodic
233 | // pauses in speech (e.g. between sentences, etc.).
234 | mouthCountdown = ((mouthPos == 0) && (random(5) == 0)) ?
235 | random(10, 40) : // Longer random duration
236 | random(2, 8); // Shorter random duration
237 | }
238 |
239 | // Refresh all of the matrices in one quick pass
240 | for(uint8_t i=0; i<4; i++) matrix[i].writeDisplay();
241 |
242 | delay(20); // ~50 FPS
243 | }
244 |
245 | // Draw mouth image across three adjacent displays
246 | void drawMouth(const uint8_t *img) {
247 | for(uint8_t i=0; i<3; i++) {
248 | matrix[MATRIX_MOUTH_LEFT + i].clear();
249 | matrix[MATRIX_MOUTH_LEFT + i].drawBitmap(i * -8, 0, img, 24, 8, LED_ON);
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/examples/LED matrix/OttoE_soundlevels/OttoE_soundlevels.ino:
--------------------------------------------------------------------------------
1 | /****************************************
2 | Scrolling Sound Meter Sketch for the
3 | Adafruit Microphone Amplifier
4 | ****************************************/
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | // Include the Matrix code for display
11 | Adafruit_8x16matrix matrix = Adafruit_8x16matrix();
12 |
13 | const int maxScale = 16;
14 | const int redZone = 5;
15 | const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
16 | unsigned int sample;
17 |
18 | void setup()
19 | {
20 | Serial.begin(9600);
21 | matrix.begin(0x70); // pass in the address
22 | }
23 |
24 | void loop()
25 | {
26 | unsigned long startMillis= millis(); // Start of sample window
27 | unsigned int peakToPeak = 0; // peak-to-peak level
28 |
29 | unsigned int signalMax = 0;
30 | unsigned int signalMin = 1024;
31 |
32 | while (millis() - startMillis < sampleWindow)
33 | {
34 | sample = analogRead(0);
35 | if (sample < 1024) // toss out spurious readings
36 | {
37 | if (sample > signalMax)
38 | {
39 | signalMax = sample; // save just the max levels
40 | }
41 | else if (sample < signalMin)
42 | {
43 | signalMin = sample; // save just the min levels
44 | }
45 | }
46 | }
47 | peakToPeak = signalMax - signalMin;
48 | double volts = (peakToPeak * 5) / 1024; // convert to volts
49 |
50 | Serial.println(volts);
51 | // map 1v p-p level to the max scale of the display
52 | int displayPeak = map(peakToPeak, 0, 1023, 0, maxScale);
53 |
54 | // Update the display:
55 | for (int i = 0; i < 7; i++) // shift the display left
56 | {
57 | matrix.displaybuffer[i] = matrix.displaybuffer[i+1];
58 | }
59 |
60 | // draw the new sample
61 | for (int i = 0; i <= maxScale; i++)
62 | {
63 | if (i >= displayPeak) // blank these pixels
64 | {
65 | matrix.drawPixel(7, i, 0);
66 | }
67 | else if (i < redZone) // draw in green
68 | {
69 | matrix.drawPixel(7, i, LED_ON);
70 | }
71 | else // Red Alert! Red Alert!
72 | {
73 | matrix.drawPixel(7, i, LED_ON);
74 | }
75 | }
76 | matrix.writeDisplay(); // write the changes we just made to the display
77 | }
78 |
--------------------------------------------------------------------------------
/examples/LED matrix/Snake8x8matrix/Snake8x8matrix.ino:
--------------------------------------------------------------------------------
1 | // Snake on 8x8Matrix
2 | // 2013-06-15 JorgVisch
3 | //
4 | #include
5 | #include
6 | #include
7 |
8 | // Button pin
9 | const int buttonRightPin = 14;
10 | const int buttonLeftPin = 16;
11 |
12 | // Game constants
13 | // buttons
14 | const int RIGHTBUTTON = 0;
15 | const int LEFTBUTTON = 1;
16 | // direction
17 | const int TOP = 0;
18 | const int RIGHT = 1;
19 | const int BOTTOM = 2;
20 | const int LEFT = 3;
21 | // Snake
22 | const int MAX_SNAKE_LENGTH = 10;
23 |
24 | // Variables
25 | Adafruit_8x8matrix matrix = Adafruit_8x8matrix(); // Display
26 | int direction = TOP; // direction of movement
27 | int snakeX[MAX_SNAKE_LENGTH]; // X-coordinates of snake
28 | int snakeY[MAX_SNAKE_LENGTH]; // Y-coordinates of snake
29 | int snakeLength = 1; // nr of parts of snake
30 | boolean buttonRead = false; // is button already read in this loop
31 | unsigned long prevTime = 0; // for gamedelay (ms)
32 | unsigned long delayTime = 500; // Game step in ms
33 |
34 | int fruitX, fruitY;
35 | unsigned long fruitPrevTime = 0;
36 | unsigned long fruitBlinkTime = 1000/250;
37 | int fruitLed = LED_ON;
38 |
39 | void setup(){
40 | Serial.begin(9600);
41 | Serial.println("Snake is started");
42 | randomSeed(analogRead(0));
43 | // Init led matrix
44 | matrix.begin(0x70);
45 | // init buttons
46 | int buttonpins[] = {buttonRightPin, buttonLeftPin};
47 | initButtons(buttonpins, 2);
48 | // init snake
49 | snakeX[0] = 4;
50 | snakeY[0] = 7;
51 | for(int i=1; i= delayTime){
61 | nextstep();
62 | buttonRead = false;
63 | prevTime = currentTime;
64 | }
65 | draw();
66 | }
67 |
68 | void checkButtons(){
69 | if(!buttonRead){
70 | int currentDirection = direction;
71 | if(buttonClicked(LEFTBUTTON)){
72 | direction--;
73 | if(direction < 0){
74 | direction = LEFT;
75 | }
76 | }
77 | else if(buttonClicked(RIGHTBUTTON)){
78 | direction++;
79 | if(direction > 3){
80 | direction = TOP;
81 | }
82 | }
83 | buttonRead = (currentDirection != direction);
84 | }
85 | }
86 |
87 | void draw(){
88 | matrix.clear();
89 | drawSnake();
90 | drawFruit();
91 | matrix.writeDisplay();
92 | }
93 |
94 | void drawSnake(){
95 | for(int i=0; i= fruitBlinkTime){
104 | fruitLed = (fruitLed == LED_ON) ? LED_OFF : LED_ON;
105 | fruitPrevTime = currenttime;
106 | }
107 | matrix.drawPixel(fruitX, fruitY, fruitLed);
108 | }
109 | }
110 |
111 | boolean inPlayField(int x, int y){
112 | return (x>=0) && (x<8) && (y>=0) && (y<8);
113 | }
114 |
115 | void nextstep(){
116 | for(int i=snakeLength-1; i>0; i--){
117 | snakeX[i] = snakeX[i-1];
118 | snakeY[i] = snakeY[i-1];
119 | }
120 | switch(direction){
121 | case TOP:
122 | snakeY[0] = snakeY[0]-1;
123 | break;
124 | case RIGHT:
125 | snakeX[0] = snakeX[0]+1;
126 | break;
127 | case BOTTOM:
128 | snakeY[0] = snakeY[0]+1;
129 | break;
130 | case LEFT:
131 | snakeX[0]=snakeX[0]-1;
132 | break;
133 | }
134 | if((snakeX[0] == fruitX) && (snakeY[0] == fruitY)){
135 | snakeLength++;
136 | if(snakeLength < MAX_SNAKE_LENGTH){
137 | makeFruit();
138 | }
139 | else {
140 | fruitX = fruitY = -1;
141 | }
142 | }
143 | }
144 |
145 | void makeFruit(){
146 | int x, y;
147 | x = random(0, 8);
148 | y = random(0, 8);
149 | while(isPartOfSnake(x, y)){
150 | x = random(0, 8);
151 | y = random(0, 8);
152 | }
153 | fruitX = x;
154 | fruitY = y;
155 | }
156 |
157 | boolean isPartOfSnake(int x, int y){
158 | for(int i=0; i
23 | #include
24 | #include
25 |
26 | //CALIBRATION SETTINGS:
27 | int LA0= 60 +0; // Left Leg standing Position - = Tilt Right + = Tilt Left
28 | int RA0= 120 +0; // Right Leg standing position - = Tilt Right + = Tilt Left
29 | int LA1= 180; // Left Leg roll Position - = Tilt Right + = Tilt Left
30 | int RA1= 0; // Right Leg roll position - = Tilt Right + = Tilt Left
31 | int LATL= LA0 +40; // Left Leg tilt left walking position - = Tilt Right + = Tilt Left
32 | int RATL= RA0 +60; // Right Leg tilt left walking position - = Tilt Right + = Tilt Left
33 | int LATR= LA0 -60; // Left Leg tilt right walking position - = Tilt Right + = Tilt Left
34 | int RATR= RA0 -40; // Right Leg tilt right walking position - = Tilt Right + = Tilt Left
35 |
36 | int LFFWRS=15; // Left foot forward walking rotation Speed 0 = SLOW 90 = FAST
37 | int RFFWRS=15 ; // Right foot forward walking rotation Speed 0 = SLOW 90 = FAST
38 | int LFBWRS= 15; // Left foot Backward walking rotation Speed 0 = SLOW 90 = FAST
39 | int RFBWRS= 15; // Right foot Backward walking rotation Speed 0 = SLOW 90 = FAST
40 |
41 |
42 | ////////////////////////////////////////
43 |
44 | const uint8_t ServoLeftFootPin = 13; //D7
45 | const uint8_t ServoLeftLegPin = 15; //D8
46 | const uint8_t ServoRightFootPin = 0; //D3
47 | const uint8_t ServoRightLegPin = 2; //D4
48 | const uint8_t ServoLeftArmPin = 16; //D0
49 | const uint8_t ServoRightArmPin = 3; //RX
50 | const uint8_t ServoHeadPin = 1; //TX
51 |
52 | Servo myservoLeftFoot;
53 | Servo myservoLeftLeg;
54 | Servo myservoRightFoot;
55 | Servo myservoRightLeg;
56 |
57 | Servo myservoLeftArm;
58 | Servo myservoRightArm;
59 | Servo myservoHead;
60 |
61 | #define echoPin 4 // attach pin D2 ESP8266 to pin Echo of HC-SR04
62 | #define trigPin 5 //attach pin D1 ESP8266 to pin Trig of HC-SR04
63 | long duration; // variable for the duration of sound wave travel
64 | int distance; // variable for the distance measurement
65 |
66 |
67 |
68 | #define ButtonPin 14 //attach pin D5 ESP8266 to pin S Button
69 | int ButtonState = 0; // variable for reading the pushbutton status
70 |
71 |
72 |
73 | #define BuzzerPin 12 //attach pin D6 ESP8266 to pin S Buzzer
74 |
75 | #define NOTE_B0 31
76 | #define NOTE_C1 33
77 | #define NOTE_CS1 35
78 | #define NOTE_D1 37
79 | #define NOTE_DS1 39
80 | #define NOTE_E1 41
81 | #define NOTE_F1 44
82 | #define NOTE_FS1 46
83 | #define NOTE_G1 49
84 | #define NOTE_GS1 52
85 | #define NOTE_A1 55
86 | #define NOTE_AS1 58
87 | #define NOTE_B1 62
88 | #define NOTE_C2 65
89 | #define NOTE_CS2 69
90 | #define NOTE_D2 73
91 | #define NOTE_DS2 78
92 | #define NOTE_E2 82
93 | #define NOTE_F2 87
94 | #define NOTE_FS2 93
95 | #define NOTE_G2 98
96 | #define NOTE_GS2 104
97 | #define NOTE_A2 110
98 | #define NOTE_AS2 117
99 | #define NOTE_B2 123
100 | #define NOTE_C3 131
101 | #define NOTE_CS3 139
102 | #define NOTE_D3 147
103 | #define NOTE_DS3 156
104 | #define NOTE_E3 165
105 | #define NOTE_F3 175
106 | #define NOTE_FS3 185
107 | #define NOTE_G3 196
108 | #define NOTE_GS3 208
109 | #define NOTE_A3 220
110 | #define NOTE_AS3 233
111 | #define NOTE_B3 247
112 | #define NOTE_C4 262
113 | #define NOTE_CS4 277
114 | #define NOTE_D4 294
115 | #define NOTE_DS4 311
116 | #define NOTE_E4 330
117 | #define NOTE_F4 349
118 | #define NOTE_FS4 370
119 | #define NOTE_G4 392
120 | #define NOTE_GS4 415
121 | #define NOTE_A4 440
122 | #define NOTE_AS4 466
123 | #define NOTE_B4 494
124 | #define NOTE_C5 523
125 | #define NOTE_CS5 554
126 | #define NOTE_D5 587
127 | #define NOTE_DS5 622
128 | #define NOTE_E5 659
129 | #define NOTE_F5 698
130 | #define NOTE_FS5 740
131 | #define NOTE_G5 784
132 | #define NOTE_GS5 831
133 | #define NOTE_A5 880
134 | #define NOTE_AS5 932
135 | #define NOTE_B5 988
136 | #define NOTE_C6 1047
137 | #define NOTE_CS6 1109
138 | #define NOTE_D6 1175
139 | #define NOTE_DS6 1245
140 | #define NOTE_E6 1319
141 | #define NOTE_F6 1397
142 | #define NOTE_FS6 1480
143 | #define NOTE_G6 1568
144 | #define NOTE_GS6 1661
145 | #define NOTE_A6 1760
146 | #define NOTE_AS6 1865
147 | #define NOTE_B6 1976
148 | #define NOTE_C7 2093
149 | #define NOTE_CS7 2217
150 | #define NOTE_D7 2349
151 | #define NOTE_DS7 2489
152 | #define NOTE_E7 2637
153 | #define NOTE_F7 2794
154 | #define NOTE_FS7 2960
155 | #define NOTE_G7 3136
156 | #define NOTE_GS7 3322
157 | #define NOTE_A7 3520
158 | #define NOTE_AS7 3729
159 | #define NOTE_B7 3951
160 | #define NOTE_C8 4186
161 | #define NOTE_CS8 4435
162 | #define NOTE_D8 4699
163 | #define NOTE_DS8 4978
164 |
165 | void setup()
166 | {
167 |
168 | NinjaHome();
169 |
170 | pinMode(BuzzerPin, OUTPUT);//buzzer
171 |
172 | pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
173 | pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
174 | pinMode(ButtonPin, INPUT_PULLUP);
175 | pinMode(BuzzerPin, OUTPUT);
176 |
177 | Serial.begin(250000);
178 |
179 | }
180 |
181 |
182 | void loop()
183 | {
184 |
185 | Distance();
186 | ButtonState = digitalRead(ButtonPin);
187 |
188 | if ((ButtonState == LOW)&&(distance >= 2)&&(distance < 7))
189 | {
190 | tone(BuzzerPin, NOTE_C5);
191 | }
192 |
193 | if ((ButtonState == LOW)&&(distance >= 7)&&(distance < 12))
194 | {
195 | tone(BuzzerPin, NOTE_D5);
196 | }
197 |
198 | if ((ButtonState == LOW)&&(distance >= 12)&&(distance < 17))
199 | {
200 | tone(BuzzerPin, NOTE_E5);
201 | }
202 |
203 | if ((ButtonState == LOW)&&(distance >= 17)&&(distance < 22))
204 | {
205 | tone(BuzzerPin, NOTE_F5);
206 | }
207 |
208 | if ((ButtonState == LOW)&&(distance >= 22)&&(distance < 27))
209 | {
210 | tone(BuzzerPin, NOTE_G5);
211 | }
212 |
213 | if ((ButtonState == LOW)&&(distance >= 27)&&(distance < 32))
214 | {
215 | tone(BuzzerPin, NOTE_A5);
216 | }
217 |
218 | if ((ButtonState == LOW)&&(distance >= 32)&&(distance < 37))
219 | {
220 | tone(BuzzerPin, NOTE_B5);
221 | }
222 |
223 | if ((ButtonState == LOW)&&(distance >= 37)&&(distance < 42))
224 | {
225 | tone(BuzzerPin, NOTE_C6);
226 | }
227 |
228 | if (ButtonState == HIGH)
229 | {
230 | noTone(BuzzerPin); // Stop sound...
231 | }
232 |
233 |
234 |
235 | }
236 |
237 | ////////////////////////////////////////////////////
238 |
239 | void NinjaHome()
240 | {
241 | myservoLeftLeg.attach(ServoLeftLegPin, 544, 2400);
242 | myservoRightLeg.attach(ServoRightLegPin, 544, 2400);
243 | myservoLeftArm.attach(ServoLeftArmPin, 544, 2400);
244 | myservoRightArm.attach(ServoRightArmPin, 544, 2400);
245 | myservoHead.attach(ServoHeadPin, 544, 2400);
246 | myservoLeftArm.write(180);
247 | myservoRightArm.write(0);
248 | myservoHead.write(90);
249 | delay(400);
250 | myservoLeftFoot.write(90);
251 | myservoRightFoot.write(90);
252 | myservoLeftLeg.write(60);
253 | myservoRightLeg.write(120);
254 | delay(400);
255 | myservoLeftLeg.detach();
256 | myservoRightLeg.detach();
257 | myservoLeftArm.detach();
258 | myservoRightArm.detach();
259 | myservoHead.detach();
260 | }
261 |
262 | void Distance()
263 | {
264 | // Clears the trigPin condition
265 | digitalWrite(trigPin, LOW);
266 | delayMicroseconds(2);
267 | // Sets the trigPin HIGH (ACTIVE) for 10 microseconds
268 | digitalWrite(trigPin, HIGH);
269 | delayMicroseconds(10);
270 | digitalWrite(trigPin, LOW);
271 | // Reads the echoPin, returns the sound wave travel time in microseconds
272 | duration = pulseIn(echoPin, HIGH);
273 | // Calculating the distance
274 | distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
275 | // Displays the distance on the Serial Monitor
276 | Serial.print("Distance: ");
277 | Serial.print(distance);
278 | Serial.println(" cm");
279 | }
280 |
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map For Otto9
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 | Otto KEYWORD1
9 | #######################################
10 | # Methods and Functions (KEYWORD2)
11 | #######################################
12 | init KEYWORD2
13 | initDC KEYWORD2
14 | initMATRIX KEYWORD2
15 | home KEYWORD2
16 | putMouth KEYWORD2
17 | writeText KEYWORD2
18 | clearMouth KEYWORD2
19 | sing KEYWORD2
20 | walk KEYWORD2
21 | playGesture KEYWORD2
22 | #######################################
23 | # Instances (KEYWORD2)
24 | #######################################
25 |
26 | #######################################
27 | # Constants (LITERAL1)
28 | #######################################
29 |
30 |
--------------------------------------------------------------------------------
/library.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "OttoDIYLib",
3 | "version": "13.0.0",
4 | "description": "Official Arduino library for controlling original Otto DIY bipedal robots",
5 | "keywords": "otto, ottodiy, robot, servo",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/OttoDIY/OttoDIYLib"
9 | },
10 | "authors": [
11 | {
12 | "name": "Otto DIY community",
13 | "url": "https://github.com/OttoDIY",
14 | "maintainer": true
15 | }
16 | ],
17 | "license": "GPL-3.0-or-later",
18 | "frameworks": "arduino",
19 | "platforms": "atmelavr"
20 | }
21 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=Otto Ninja
2 | version=1.0
3 | author=Sebastian Coddington
4 | maintainer=Sebastian Coddington, Camilo Parra Palacio
5 | sentence=Libraries for controlling Otto Ninja bipedal robot starter and Humanoid.
6 | paragraph=Otto Ninja can walk, transform, roll, show emotions, dance, sense motion and objects. Program Otto Ninja to think on it’s own using block-based coding with Blockly and C++ with Arduino IDE.
7 |
8 | category=Device Control
9 | url=https://github.com/OttoDIY/
10 | architectures=esp8266
11 |
--------------------------------------------------------------------------------
/src/RemoteXY.h:
--------------------------------------------------------------------------------
1 | /* RemoteXY.h
2 | A RemoteXY Library - Remote device control
3 | version 3.1.7
4 | ===========================================================
5 | For use RemoteXY library visit website http://remotexy.com
6 | This website will help you use the library for configuring
7 | a remote control from a smartphone or tablet.
8 |
9 | This library is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU Lesser General Public
11 | License as published by the Free Software Foundation; either
12 | version 2.1 of the License, or (at your option) any later version.
13 |
14 | Supported modes:
15 | All boards:
16 | #define REMOTEXY_MODE__HARDSERIAL - direct data transfer via HARDSERIAL
17 | #define REMOTEXY_MODE__SOFTSERIAL - direct data transfer via SOFTSERIAL
18 | #define REMOTEXY_MODE__CDCSERIAL - direct data transfer via CDC for ATmega32u4
19 | #define REMOTEXY_MODE__ETHERNET - data transfer using library and open server
20 | #define REMOTEXY_MODE__ETHERNET_CLOUD - data transfer using library and cloud connection
21 | #define REMOTEXY_MODE__HARDSERIAL_ESP8266 - data transfer via HARDSERIAL using AT commands of ESP8266 and open server
22 | #define REMOTEXY_MODE__HARDSERIAL_ESP8266_POINT - data transfer via HARDSERIAL using AT commands of ESP8266 and open access point with a server
23 | #define REMOTEXY_MODE__HARDSERIAL_ESP8266_CLOUD - data transfer via HARDSERIAL using AT commands of ESP8266 and cloud connection
24 | #define REMOTEXY_MODE__SOFTSERIAL_ESP8266 - data transfer via SOFTSERIAL using AT commands of ESP8266 and open server
25 | #define REMOTEXY_MODE__SOFTSERIAL_ESP8266_POINT - data transfer via SOFTSERIAL using AT commands of ESP8266 and open access point with a server
26 | #define REMOTEXY_MODE__SOFTSERIAL_ESP8266_CLOUD - data transfer via SOFTSERIAL using AT commands of ESP8266 and cloud connection
27 | #define REMOTEXY_MODE__WIFI - data transfer using generic wifi.h library and open server
28 | #define REMOTEXY_MODE__WIFI_POINT - data transfer using generic wifi.h library and open access point with a server
29 | #define REMOTEXY_MODE__WIFI_CLOUD - data transfer using generic wifi.h library and cloud connection
30 |
31 | Only ESP8266 boards:
32 | #define REMOTEXY_MODE__ESP8266CORE_ESP8266WIFI or REMOTEXY_MODE__WIFI - data transfer using library and open server
33 | #define REMOTEXY_MODE__ESP8266CORE_ESP8266WIFI_POINT or REMOTEXY_MODE__WIFI_POINT - data transfer using library and open access point with a server
34 | #define REMOTEXY_MODE__ESP8266CORE_ESP8266WIFI_CLOUD or REMOTEXY_MODE__WIFI_CLOUD - data transfer using library and cloud connection
35 |
36 | Only ESP32 boards:
37 | #define REMOTEXY_MODE__ESP32CORE_WIFI or REMOTEXY_MODE__WIFI - data transfer using library and open server
38 | #define REMOTEXY_MODE__ESP32CORE_WIFI_POINT or REMOTEXY_MODE__WIFI_POINT - data transfer using library and open access point with a server
39 | #define REMOTEXY_MODE__ESP32CORE_WIFI_CLOUD or REMOTEXY_MODE__WIFI_CLOUD - data transfer using library and cloud connection
40 | #define REMOTEXY_MODE__ESP32CORE_BLE - data transfer using library
41 | #define REMOTEXY_MODE__ESP32CORE_BLUETOOTH - data transfer using library
42 |
43 | Only NRF52xx based boards:
44 | #define REMOTEXY_MODE__NRFCORE_BLEPERIPHERAL - data transfer using library
45 |
46 | Parameters depending on the selected mode (for example):
47 | #define REMOTEXY_SERIAL Serial // for Hardware Serial
48 | #define REMOTEXY_SERIAL_SPEED 115200
49 | #define REMOTEXY_SERIAL_RX 2 // for Software Serial
50 | #define REMOTEXY_SERIAL_TX 3 // for Software Serial
51 | #define REMOTEXY_WIFI_SSID "RemoteXY"
52 | #define REMOTEXY_WIFI_PASSWORD "1234567890"
53 | #define REMOTEXY_ETHERNET_MAC "DE:AD:BE:EF:EF:ED" // for Ethernet modules
54 | #define REMOTEXY_SERVER_PORT 6377
55 | #define REMOTEXY_BLUETOOTH_NAME "remotexy" // for ESP32
56 | #define REMOTEXY_CLOUD_TOKEN "xxxx" // for Cloud
57 | #define REMOTEXY_CLOUD_SERVER "cloud.remotexy.com" // for Cloud
58 | #define REMOTEXY_CLOUD_PORT 6376 // for Cloud
59 | #define REMOTEXY_ACCESS_PASSWORD "1"
60 |
61 | Debug log info on serial 115200 (define before include this library):
62 | #define REMOTEXY__DEBUGLOG
63 | #define REMOTEXY__DEBUGLOG_SERIAL Serial
64 | #define REMOTEXY__DEBUGLOG_SPEED 115200
65 |
66 | = Version history ========================================
67 |
68 | version 2.2.5
69 | - support MPIDE;
70 | version 2.3.1
71 | - Support the device access password;
72 | - Support the cloud server as beta test;
73 | - Fixed a bug where the length of variables more than 255;
74 | - Fixed a bug where ESP module reboot and device did not see it;
75 | - Fixed a bug where the connection was filed and the device
76 | did not see it and reconnection is impossible
77 | version 2.3.4
78 | - Fixed a bug where the length of all input variables more than 256;
79 | - Fixed a bug where millis() overflow in 50 days;
80 | - Fixed some bugs;
81 | version 2.3.5
82 | - Fixed some bugs;
83 | version 2.4.1
84 | - support ESP32 WiFi and Bluetooth
85 | version 2.4.2
86 | - Fixed some bugs;
87 | version 2.4.3
88 | - Fixed some bugs;
89 | version 2.4.4
90 | - Fixed ESP32 BLE bugs;
91 | version 3.1.1
92 | - Full update the library: multiple connections, set input variables from board and more;
93 | version 3.1.3
94 | - Multiple connection for cloud, fixed some bugs;
95 | version 3.1.4
96 | - fixed some bugs;
97 | version 3.1.5
98 | - add NRF5XXX and BLEPeripheral.h library as Beta, need define REMOTEXY_MODE__NRFCORE_BLEPERIPHERAL;
99 | version 3.1.6
100 | - fixed some bugs;
101 | version 3.1.7
102 | - add CDC Serial for Leonardo, Micro, ..;
103 |
104 | */
105 |
106 | #ifndef _REMOTEXY_H_
107 | #define _REMOTEXY_H_
108 |
109 |
110 |
111 | #ifndef REMOTEXY_MAX_CLIENTS
112 | #define REMOTEXY_MAX_CLIENTS 4
113 | #endif
114 |
115 |
116 | //#define REMOTEXY__DEBUGLOG
117 | //#define REMOTEXY__DEBUGLOG_SERIAL Serial
118 | //#define REMOTEXY__DEBUGLOG_SPEED 115200
119 |
120 |
121 | #include
122 | #include
123 | #include "RemoteXYDebugLog.h"
124 |
125 | #if defined(REMOTEXY_MODE__ESP32CORE_BLUETOOTH)
126 | #include "BluetoothSerial.h"
127 | #elif defined(REMOTEXY_MODE__ESP32CORE_BLE)
128 | #include "BLEDevice.h"
129 |
130 | #endif
131 |
132 |
133 | #include "RemoteXYApi.h"
134 |
135 | #include "RemoteXYStream_HardSerial.h"
136 | #include "RemoteXYStream_SoftSerial.h" // need SoftwareSerial.h or SoftSerial.h
137 | #include "RemoteXYStream_CDCSerial.h"
138 | #include "RemoteXYStream_BluetoothSerial.h" // need BluetoothSerial.h
139 | #include "RemoteXYStream_BLEDevice.h" // need BLEDevice.h
140 | #include "RemoteXYStream_BLEPeripheral.h" // need BLEPeripheral.h
141 | #include "RemoteXYComm_WiFi.h" // need ESP8266WiFi.h (ESP8266) or WiFi.h (ESP32) or WiFi.h (Arduino shield)
142 | #include "RemoteXYComm_Ethernet.h" // need Ethernet.h
143 | #include "RemoteXYComm_ESP8266.h"
144 |
145 |
146 | #ifndef REMOTEXY_ACCESS_PASSWORD
147 | #define REMOTEXY_ACCESS_PASSWORD ""
148 | #endif
149 |
150 |
151 | #define RemoteXY_Handler() remotexy->handler ()
152 | #define RemoteXY_CONF const PROGMEM RemoteXY_CONF_PROGMEM
153 |
154 | // predefined configurations
155 |
156 | #if defined(REMOTEXY_MODE__HARDSERIAL) || defined(REMOTEXY_MODE__SERIAL) || defined(REMOTEXY_MODE__HC05_HARDSERIAL)
157 | CRemoteXY *remotexy;
158 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYStream_HardSerial (&REMOTEXY_SERIAL, REMOTEXY_SERIAL_SPEED))
159 |
160 | #elif defined(REMOTEXY_MODE__SOFTSERIAL) || defined(REMOTEXY_MODE__SOFTWARESERIAL) || defined(REMOTEXY_MODE__HC05_SOFTSERIAL)
161 | CRemoteXY *remotexy;
162 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYStream_SoftSerial (REMOTEXY_SERIAL_RX, REMOTEXY_SERIAL_TX, REMOTEXY_SERIAL_SPEED))
163 |
164 | #elif defined(REMOTEXY_MODE__CDCSERIAL)
165 | CRemoteXY *remotexy;
166 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYStream_CDCSerial (&REMOTEXY_SERIAL, REMOTEXY_SERIAL_SPEED))
167 |
168 | #elif defined(REMOTEXY_MODE__ESP32CORE_BLE)
169 | CRemoteXY *remotexy;
170 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYStream_BLEDevice (REMOTEXY_BLUETOOTH_NAME))
171 |
172 | #elif defined(REMOTEXY_MODE__ESP32CORE_WIFI) || defined(REMOTEXY_MODE__ESP8266CORE_ESP8266WIFI) || defined(REMOTEXY_MODE__ESP8266WIFI_LIB) || defined(REMOTEXY_MODE__WIFI)
173 | CRemoteXY *remotexy;
174 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionServer (new CRemoteXYComm_WiFi (REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_SERVER_PORT))
175 |
176 | #elif defined(REMOTEXY_MODE__ESP32CORE_WIFI_POINT) || defined(REMOTEXY_MODE__ESP8266CORE_ESP8266WIFI_POINT) || defined(REMOTEXY_MODE__ESP8266WIFI_LIB_POINT) || defined(REMOTEXY_MODE__ESP8266WIFIPOINT_LIB) || defined(REMOTEXY_MODE__WIFI_POINT)
177 | CRemoteXY *remotexy;
178 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionServer (new CRemoteXYComm_WiFiPoint (REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_SERVER_PORT))
179 |
180 | #elif defined(REMOTEXY_MODE__ESP32CORE_WIFI_CLOUD) || defined(REMOTEXY_MODE__ESP8266CORE_ESP8266WIFI_CLOUD) || defined(REMOTEXY_MODE__ESP8266WIFI_LIB_CLOUD) || defined(REMOTEXY_MODE__WIFI_CLOUD)
181 | CRemoteXY *remotexy;
182 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionCloud (new CRemoteXYComm_WiFi (REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_CLOUD_SERVER, REMOTEXY_CLOUD_PORT, REMOTEXY_CLOUD_TOKEN))
183 |
184 | #elif defined(REMOTEXY_MODE__HARDSERIAL_ESP8266_POINT) || defined(REMOTEXY_MODE__ESP8266_HARDSERIAL_POINT) || defined(REMOTEXY_MODE__ESP8266POINT_HARDSERIAL)
185 | CRemoteXY *remotexy;
186 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionServer (new CRemoteXYComm_ESP8266Point (new CRemoteXYStream_HardSerial (&REMOTEXY_SERIAL, REMOTEXY_SERIAL_SPEED), REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_SERVER_PORT))
187 |
188 | #elif defined(REMOTEXY_MODE__SOFTSERIAL_ESP8266_POINT) || defined(REMOTEXY_MODE__ESP8266_SOFTSERIAL_POINT) || defined(REMOTEXY_MODE__ESP8266POINT_SOFTSERIAL)
189 | CRemoteXY *remotexy;
190 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionServer (new CRemoteXYComm_ESP8266Point (new CRemoteXYStream_SoftSerial (REMOTEXY_SERIAL_RX, REMOTEXY_SERIAL_TX, REMOTEXY_SERIAL_SPEED), REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_SERVER_PORT))
191 |
192 | #elif defined(REMOTEXY_MODE__HARDSERIAL_ESP8266) || defined(REMOTEXY_MODE__ESP8266_HARDSERIAL)
193 | CRemoteXY *remotexy;
194 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionServer (new CRemoteXYComm_ESP8266 (new CRemoteXYStream_HardSerial (&REMOTEXY_SERIAL, REMOTEXY_SERIAL_SPEED), REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_SERVER_PORT))
195 |
196 | #elif defined(REMOTEXY_MODE__SOFTSERIAL_ESP8266) || defined(REMOTEXY_MODE__ESP8266_SOFTSERIAL)
197 | CRemoteXY *remotexy;
198 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionServer (new CRemoteXYComm_ESP8266 (new CRemoteXYStream_SoftSerial (REMOTEXY_SERIAL_RX, REMOTEXY_SERIAL_TX, REMOTEXY_SERIAL_SPEED), REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_SERVER_PORT))
199 |
200 | #elif defined(REMOTEXY_MODE__HARDSERIAL_ESP8266_CLOUD) || defined(REMOTEXY_MODE__ESP8266_HARDSERIAL_CLOUD)
201 | CRemoteXY *remotexy;
202 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionCloud (new CRemoteXYComm_ESP8266 (new CRemoteXYStream_HardSerial (&REMOTEXY_SERIAL, REMOTEXY_SERIAL_SPEED), REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_CLOUD_SERVER, REMOTEXY_CLOUD_PORT, REMOTEXY_CLOUD_TOKEN))
203 |
204 | #elif defined(REMOTEXY_MODE__SOFTSERIAL_ESP8266_CLOUD) || defined(REMOTEXY_MODE__ESP8266_SOFTSERIAL_CLOUD)
205 | CRemoteXYCloud *remotexy;
206 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionCloud (new CRemoteXYComm_ESP8266 (new CRemoteXYStream_SoftSerial (REMOTEXY_SERIAL_RX, REMOTEXY_SERIAL_TX, REMOTEXY_SERIAL_SPEED), REMOTEXY_WIFI_SSID, REMOTEXY_WIFI_PASSWORD), REMOTEXY_CLOUD_SERVER, REMOTEXY_CLOUD_PORT, REMOTEXY_CLOUD_TOKEN))
207 |
208 | #elif defined(REMOTEXY_MODE__ETHERNET) || defined(REMOTEXY_MODE__ETHERNET_LIB) || defined(REMOTEXY_MODE__W5100_SPI)
209 | CRemoteXY *remotexy;
210 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionServer (new CRemoteXYComm_Ethernet (REMOTEXY_ETHERNET_MAC), REMOTEXY_SERVER_PORT))
211 |
212 | #elif defined(REMOTEXY_MODE__ETHERNET_CLOUD) || defined(REMOTEXY_MODE__ETHERNET_LIB_CLOUD)
213 | CRemoteXY *remotexy;
214 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYConnectionCloud (new CRemoteXYComm_Ethernet (REMOTEXY_ETHERNET_MAC), REMOTEXY_CLOUD_SERVER, REMOTEXY_CLOUD_PORT, REMOTEXY_CLOUD_TOKEN))
215 |
216 | #elif defined(REMOTEXY_MODE__ESP32CORE_BLUETOOTH)
217 | CRemoteXY *remotexy;
218 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYStream_BluetoothSerial (REMOTEXY_BLUETOOTH_NAME))
219 |
220 | #elif defined(REMOTEXY_MODE__NRFCORE_BLEPERIPHERAL)
221 | CRemoteXY *remotexy;
222 | #define RemoteXY_Init() remotexy = new CRemoteXY (RemoteXY_CONF_PROGMEM, &RemoteXY, REMOTEXY_ACCESS_PASSWORD, new CRemoteXYStream_BLEPeripheral (REMOTEXY_BLUETOOTH_NAME))
223 |
224 | #endif
225 |
226 | //API
227 | #define RemoteXY_isConnected() remotexy->isConnected ()
228 |
229 |
230 | #endif //_REMOTEXY_H_
231 |
232 |
--------------------------------------------------------------------------------
/src/RemoteXYApi.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYApi_h
2 | #define RemoteXYApi_h
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "RemoteXYDebugLog.h"
9 | #include "RemoteXYApiData.h"
10 | #include "RemoteXYConnection.h"
11 | #include "RemoteXYConnectionStream.h"
12 | #include "RemoteXYConnectionServer.h"
13 | #include "RemoteXYConnectionCloud.h"
14 |
15 | #include "RemoteXYComm.h"
16 | #include "RemoteXYCloudServer.h"
17 | #include "RemoteXYThread.h"
18 | #include "RemoteXYWire.h"
19 | #include "RemoteXYWireStream.h"
20 |
21 | #include "RemoteXYCloudServer.h"
22 |
23 |
24 |
25 | class CRemoteXY {
26 | public:
27 | CRemoteXYData data;
28 |
29 |
30 | public:
31 | CRemoteXY (const void * _conf, void * _var, const char * _accessPassword) {
32 | data.init (_conf, _var, _accessPassword);
33 |
34 | #if defined(REMOTEXY__DEBUGLOG)
35 | RemoteXYDebugLog.init ();
36 | RemoteXYDebugLog.write("RemoteXY started");
37 | #endif
38 | }
39 |
40 | public:
41 | CRemoteXY (const void * _conf, void * _var, const char * _accessPassword, CRemoteXYConnectionComm * _conn) {
42 | data.init (_conf, _var, _accessPassword);
43 | addConnection (_conn);
44 |
45 | #if defined(REMOTEXY__DEBUGLOG)
46 | RemoteXYDebugLog.init ();
47 | RemoteXYDebugLog.write("RemoteXY started");
48 | #endif
49 | }
50 |
51 | public:
52 | CRemoteXY (const void * _conf, void * _var, const char * _accessPassword, CRemoteXYStream * _comm) {
53 | data.init (_conf, _var, _accessPassword);
54 | addConnection (_comm);
55 |
56 | #if defined(REMOTEXY__DEBUGLOG)
57 | RemoteXYDebugLog.init ();
58 | RemoteXYDebugLog.write("RemoteXY started");
59 | #endif
60 | }
61 |
62 |
63 |
64 | public:
65 | void addConnection (CRemoteXYConnectionComm * conn) {
66 | CRemoteXYComm * p = data.comms;
67 | while (p) {
68 | if (p == conn->comm) break;
69 | p = p->next;
70 | }
71 | if (!p) {
72 | conn->comm->next = data.comms;
73 | data.comms = conn->comm;
74 | }
75 | conn->next = data.connections;
76 | data.connections = conn;
77 | conn->init (&data);
78 | }
79 |
80 | public:
81 | void addConnection (CRemoteXYStream * comm) {
82 | CRemoteXYConnection * conn = new CRemoteXYConnectionStream (comm);
83 | conn->init (&data);
84 | }
85 |
86 |
87 | public:
88 | void handler () {
89 | uint8_t connect_flag = 0;
90 |
91 | // threads handler
92 |
93 | CRemoteXYThread * pt = data.threads;
94 | while (pt) {
95 | pt->handler ();
96 | connect_flag += pt->connect_flag;
97 | pt = pt->next;
98 | }
99 | *data.connect_flag = connect_flag;
100 |
101 | // communications handler
102 |
103 | CRemoteXYComm * comm = data.comms;
104 | while (comm) {
105 | comm->handler ();
106 | comm = comm->next;
107 | }
108 |
109 | // connections handler
110 |
111 | CRemoteXYConnectionComm * connection = data.connections;
112 | while (connection) {
113 | connection->handler ();
114 | connection = connection->next;
115 | }
116 |
117 |
118 | }
119 |
120 |
121 |
122 | ///////////////////////////////////////////////////////////////////////////////
123 | // API - PUBLIC DOCUMENTED FUNCTIONS
124 |
125 |
126 | public:
127 | uint8_t isConnected () {
128 | return *data.connect_flag;
129 | }
130 |
131 | };
132 |
133 |
134 |
135 |
136 |
137 | #endif //RemoteXYApi_h
138 |
139 |
--------------------------------------------------------------------------------
/src/RemoteXYApiData.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYApiData_h
2 | #define RemoteXYApiData_h
3 |
4 | #include
5 |
6 |
7 | #define REMOTEXY_PASSWORD_LENGTH_MAX 26
8 |
9 | class CRemoteXYThread;
10 | class CRemoteXYComm;
11 | class CRemoteXYConnectionComm;
12 |
13 |
14 | class CRemoteXYData {
15 |
16 | public:
17 | uint8_t confVersion;
18 | uint8_t *conf;
19 | uint8_t *var;
20 | uint8_t *accessPassword;
21 | uint16_t outputLength;
22 | uint16_t inputLength;
23 | uint16_t confLength;
24 | uint8_t *connect_flag;
25 |
26 | uint16_t receiveBufferSize;
27 |
28 | CRemoteXYThread * threads;
29 | CRemoteXYComm * comms;
30 | CRemoteXYConnectionComm * connections;
31 |
32 |
33 | public:
34 | void init (const void * _conf, void * _var, const char * _accessPassword) {
35 |
36 | uint8_t i;
37 | uint8_t* p = (uint8_t*)_conf;
38 | uint8_t b = getConfByte (p++);
39 |
40 | if (b==0xff) {
41 | inputLength = getConfByte (p++);
42 | inputLength |= getConfByte (p++)<<8;
43 | outputLength = getConfByte (p++);
44 | outputLength |= getConfByte (p++)<<8;
45 | }
46 | else {
47 | inputLength = b;
48 | outputLength = getConfByte (p++);
49 | }
50 | confLength = getConfByte (p++);
51 | confLength |= getConfByte (p++)<<8;
52 | conf = p;
53 | confVersion = getConfByte (p);
54 | var = (uint8_t*)_var;
55 | uint16_t varLength = outputLength + inputLength;
56 | connect_flag = var + varLength;
57 | *connect_flag = 0;
58 |
59 | accessPassword = (uint8_t*)_accessPassword;
60 |
61 | p = var;
62 | i = varLength;
63 | while (i--) *p++=0;
64 |
65 | receiveBufferSize = inputLength;
66 | if ((*accessPassword != 0) && (receiveBufferSize < REMOTEXY_PASSWORD_LENGTH_MAX)) receiveBufferSize = REMOTEXY_PASSWORD_LENGTH_MAX;
67 | receiveBufferSize +=6;
68 |
69 | comms = NULL;
70 | connections = NULL;
71 | threads = NULL;
72 | }
73 |
74 | public:
75 | inline uint8_t getConfByte (uint8_t* p) {
76 | return pgm_read_byte_near (p);
77 | }
78 |
79 |
80 | };
81 |
82 |
83 |
84 |
85 | #endif //RemoteXYData_h
--------------------------------------------------------------------------------
/src/RemoteXYCloudServer.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYCloudServer_h
2 | #define RemoteXYCloudServer_h
3 |
4 |
5 | #include "RemoteXYApiData.h"
6 | #include "RemoteXYComm.h"
7 | #include "RemoteXYWire.h"
8 | #include "RemoteXYWireStream.h"
9 | #include "RemoteXYWireCloud.h"
10 |
11 | #define REMOTEXY_CLOUD_CONNECT_TIMEOUT 10000
12 | #define REMOTEXY_CLOUD_ECHO_TIMEOUT 30000
13 |
14 |
15 | class CRemoteXYCloudClientAvailableListener {
16 | public:
17 | virtual void clientAvailable (CRemoteXYWireCloud * wire) = 0;
18 | };
19 |
20 |
21 | class CRemoteXYCloudServer : public CRemoteXYReceivePackageListener, CRemoteXYSendPackageListener {
22 | public:
23 | CRemoteXYWireStream * wire;
24 | CRemoteXYWireCloud * cloudWires;
25 |
26 | private:
27 | CRemoteXYCloudClientAvailableListener * clientAvailableListener;
28 |
29 | uint8_t cloudRegistPackage[38];
30 | enum { Registring, Working, Stopped } state;
31 | uint32_t timeOut;
32 |
33 |
34 | public:
35 | CRemoteXYCloudServer (CRemoteXYData * data, const char * _cloudToken, CRemoteXYCloudClientAvailableListener * listener) {
36 |
37 |
38 | uint8_t i;
39 | uint8_t *p = cloudRegistPackage;
40 | *p++ = data->getConfByte(data->conf+0);
41 | *p++ = 0;
42 | for (i=0; i<32; i++) {
43 | if (*_cloudToken==0) *(p++)=0;
44 | else *(p++)=*(_cloudToken++);
45 | }
46 | uint16_t *len = (uint16_t*)p;
47 | *len = data->outputLength + data->inputLength;
48 | if (data->confLength>*len) *len = data->confLength;
49 | *len += 6+1;
50 | len = (uint16_t*)(p+2);
51 | *len = data->receiveBufferSize;
52 | #if REMOTEXY_MAX_CLIENTS == 1
53 | wire = new CRemoteXYWireStream (data);
54 | #else
55 | wire = new CRemoteXYWireStream (data, 2);
56 | #endif
57 | cloudWires = NULL;
58 | state = Stopped;
59 |
60 | clientAvailableListener = listener;
61 | }
62 |
63 |
64 | public:
65 | void begin (CRemoteXYClient * client) {
66 | wire->begin(client);
67 | wire->setReceivePackageListener (this);
68 | state = Registring;
69 | wire->sendPackage (0x11, cloudRegistPackage, 38, 0);
70 | timeOut = millis ();
71 | }
72 |
73 | public:
74 | void stop () {
75 | if (state != Stopped) {
76 | wire->stop ();
77 | state = Stopped;
78 | #if defined(REMOTEXY__DEBUGLOG)
79 | RemoteXYDebugLog.write ("Cloud server stoped");
80 | #endif
81 | }
82 | }
83 |
84 | public:
85 | uint8_t running () {
86 | if (state != Stopped) return 1;
87 | return 0;
88 | }
89 |
90 |
91 | public:
92 | void handler () {
93 | if (state != Stopped) {
94 | CRemoteXYClient * client = wire->getClient ();
95 | wire->handler ();
96 | if (!client->connected ()) stop ();
97 | if (wire->running ()) {
98 |
99 | if (state == Registring) {
100 | if (millis() - timeOut > REMOTEXY_CLOUD_CONNECT_TIMEOUT) stop ();
101 | }
102 | else if (state == Working) {
103 | if (millis() - timeOut > REMOTEXY_CLOUD_ECHO_TIMEOUT) {
104 | #if defined(REMOTEXY__DEBUGLOG)
105 | RemoteXYDebugLog.write("Cloud server timed out");
106 | #endif
107 | stop ();
108 | }
109 | }
110 | }
111 | else stop ();
112 | }
113 | }
114 |
115 | public:
116 | void sendPackage (uint8_t command, uint8_t *buf, uint16_t length, uint8_t fromPgm) override {
117 | wire->sendPackage (command, buf, length, fromPgm);
118 | }
119 |
120 |
121 | public:
122 | void receivePackage (CRemoteXYPackage * package) override {
123 | timeOut = millis ();
124 | if (package->command == 0x10) {
125 | wire->sendPackage (0x10, 0, 0, 0);
126 | }
127 | else if (package->command == 0x11) {
128 | state = Working;
129 | #if defined(REMOTEXY__DEBUGLOG)
130 | RemoteXYDebugLog.write ("Cloud server registration successfully");
131 | #endif
132 | }
133 | else {
134 | uint8_t id = (package->command & 0x0e)>>1;
135 | package->command &= 0xf1;
136 |
137 | CRemoteXYWireCloud * pw = cloudWires;
138 | while (pw) {
139 | if ((pw->running ()) && (pw->id == id)) {
140 | pw->receivePackage (package);
141 | return;
142 | }
143 | pw = pw->next;
144 | }
145 | pw = getFreeWireCloud ();
146 | pw->init (id);
147 | clientAvailableListener->clientAvailable (pw);
148 | pw->receivePackage (package);
149 | }
150 | }
151 |
152 | private:
153 | CRemoteXYWireCloud * getFreeWireCloud () {
154 | CRemoteXYWireCloud * pw = cloudWires;
155 | while (pw) {
156 | if (!pw->running ()) return pw;
157 | pw = pw->next;
158 | }
159 | pw = new CRemoteXYWireCloud (this);
160 | pw->next = cloudWires;
161 | cloudWires = pw;
162 | return pw;
163 | }
164 | };
165 |
166 |
167 |
168 | #endif //RemoteXYCloudServer_h
--------------------------------------------------------------------------------
/src/RemoteXYComm.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYComm_h
2 | #define RemoteXYComm_h
3 |
4 | #include
5 | #include "RemoteXYDebugLog.h"
6 | #include "RemoteXYStream.h"
7 |
8 |
9 | #define UNUSED(x) (void)(x)
10 |
11 | class CRemoteXYClientAvailableListener {
12 | public:
13 | virtual void clientAvailable () = 0;
14 | };
15 |
16 |
17 |
18 | class CRemoteXYClient: public CRemoteXYStream {
19 | public:
20 | CRemoteXYClient * next;
21 |
22 | public:
23 | CRemoteXYClient (): CRemoteXYStream() {
24 | }
25 |
26 | public:
27 | virtual uint8_t connect (const char *host, uint16_t port) {UNUSED (host); UNUSED (port); return 0;};
28 | virtual void stop () {};
29 | virtual uint8_t connected () {return 1;};
30 | virtual uint8_t equal (CRemoteXYClient * cl) {UNUSED (cl); return 0;}
31 | };
32 |
33 |
34 | class CRemoteXYServer {
35 |
36 | private:
37 | CRemoteXYClientAvailableListener * clientAvailableListener;
38 |
39 | public:
40 | void setClientAvailabListener (CRemoteXYClientAvailableListener * listener) {
41 | clientAvailableListener = listener;
42 | }
43 |
44 | public:
45 | void notifyClientAvailableListener () {
46 | if (clientAvailableListener) clientAvailableListener->clientAvailable ();
47 | }
48 |
49 |
50 | public:
51 | virtual uint8_t begin () {return 0;}
52 | virtual void stop () {};
53 | virtual uint8_t available (CRemoteXYClient * client) {UNUSED (client); return 0;}
54 |
55 | };
56 |
57 |
58 |
59 | class CRemoteXYComm {
60 | public:
61 | CRemoteXYComm * next;
62 |
63 | public:
64 | CRemoteXYComm () {
65 | #if defined(REMOTEXY__DEBUGLOG)
66 | RemoteXYDebugLog.init ();
67 | #endif
68 | }
69 |
70 | public:
71 | virtual void handler () {};
72 | virtual uint8_t configured () {return 1;};
73 | virtual CRemoteXYServer * createServer (uint16_t _port) {UNUSED (_port); return NULL;}
74 | virtual CRemoteXYClient * newClient () {return NULL;}
75 | };
76 |
77 |
78 |
79 | #endif //RemoteXYComm_h
--------------------------------------------------------------------------------
/src/RemoteXYComm_AT.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYComm_AT_h
2 | #define RemoteXYComm_AT_h
3 |
4 | #include "RemoteXYDebugLog.h"
5 | #include "RemoteXYComm.h"
6 | #include "RemoteXYFunc.h"
7 | #include
8 |
9 | #define UNUSED(x) (void)(x)
10 |
11 | #define REMOTEXYCOMM_AT__RECEIVE_BUFFER_SIZE 32 // maximum response length
12 |
13 | #define REMOTEXYCOMM_AT__COMMAND_TIMEOUT 1000
14 | #define REMOTEXYCOMM_AT__SEND_TIMEOUT 5000
15 | #define REMOTEXYCOMM_AT__TEST_TIMEOUT 30000
16 | #define REMOTEXYCOMM_AT__CONNECT_TIMEOUT 20000
17 | #define REMOTEXYCOMM_AT__NO_CHANNEL 0xff
18 |
19 |
20 | #define AT_ID_BLOCKING 255
21 | #define AT_ID_FINDMODULE 254
22 | #define AT_ID_TESTMODULE 253
23 |
24 | #define AT_RESULT_OK 1
25 | #define AT_RESULT_TIMEOUT 2
26 | #define AT_RESULT_ERROR 3
27 | #define AT_RESULT_FAIL 4
28 | #define AT_RESULT_BUSY 5
29 | #define AT_RESULT_RESET 6
30 | #define AT_RESULT_SEND_READY 7
31 | #define AT_RESULT_SEND_OK 8
32 | #define AT_RESULT_SEND_FAIL 9
33 | #define AT_RESULT_MESSAGE 10
34 |
35 | // standards answers
36 | const char * AT_ANSWER_ERROR = "ERROR";
37 | const char * AT_ANSWER_FAIL = "FAIL";
38 | const char * AT_ANSWER_BUSY = "BUSY *";
39 | const char * AT_ANSWER_OK = "OK";
40 | const char * AT_ANSWER_SEND_OK = "SEND OK";
41 | const char * AT_ANSWER_SEND_FAIL = "SEND FAIL";
42 | const char * AT_MESSAGE_READY = "READY";
43 | const char * AT_MESSAGE_AT = "AT";
44 | const char * AT_MESSAGE_CONNECT = "?,CONNECT";
45 | const char * AT_MESSAGE_CLOSED = "?,CLOSED";
46 | const char * AT_MESSAGE_CONNECT_FAIL = "?,CONNECT FAIL";
47 | const char * AT_MESSAGE_IPD = "+IPD,?,*:";
48 | const char * AT_MESSAGE_CIPSEND = "AT+CIPSEND=";
49 | const char * AT_MESSAGE_CIPCLOSE = "AT+CIPCLOSE=";
50 | const char * AT_MESSAGE_CIPSTART = "AT+CIPSTART=";
51 |
52 |
53 |
54 | class CRemoteXYClient_AT;
55 | class CRemoteXYComm_AT;
56 |
57 | class CRemoteXYClient_AT_Proto : public CRemoteXYClient {
58 | public:
59 | CRemoteXYComm_AT * comm;
60 | uint8_t id;
61 | uint8_t _connected;
62 | CRemoteXYClient_AT_Proto * next;
63 |
64 | };
65 |
66 |
67 |
68 | class CRemoteXYComm_AT : public CRemoteXYComm, public CRemoteXYReadByteListener {
69 |
70 | private:
71 | CRemoteXYStream * serial;
72 |
73 | public:
74 | CRemoteXYServer * server;
75 | CRemoteXYClient_AT_Proto * clients;
76 |
77 |
78 | protected:
79 | char receiveBuffer[REMOTEXYCOMM_AT__RECEIVE_BUFFER_SIZE];
80 | uint8_t receiveBufferIndex;
81 |
82 | char * params[3];
83 | uint8_t paramsLength[3];
84 |
85 | uint32_t lastAnswerTime;
86 |
87 |
88 | uint16_t connectAvailable;
89 | uint16_t freeAvailable;
90 |
91 |
92 |
93 | uint32_t commandTimeOut;
94 | uint32_t commandDelay;
95 | uint8_t commandIdentifier;
96 | void (*commandListener)(uint8_t, uint8_t);
97 | volatile uint8_t commandResult;
98 | volatile uint8_t commandBlocking;
99 | uint8_t commandFlag;
100 |
101 | uint16_t ipdId;
102 | uint16_t ipdSize;
103 | CRemoteXYClient_AT_Proto * ipdClient;
104 |
105 | int8_t availableClientID;
106 |
107 | uint8_t findModuleTryCount;
108 | uint8_t haveEcho;
109 |
110 | uint16_t sendByteMax;
111 | uint16_t sendByteSize;
112 | uint16_t sendByteNext;
113 |
114 | uint8_t clientConnectingID;
115 | uint8_t detected;
116 |
117 | public:
118 | virtual void moduleReset () {};
119 | virtual void moduleLost () {};
120 | virtual void moduleFound () {};
121 | virtual uint8_t handleATMessage () {return 0;};
122 | virtual void commandATListener (uint8_t identifier, uint8_t result) { UNUSED(identifier); UNUSED(result);};
123 |
124 |
125 |
126 |
127 |
128 | public:
129 | CRemoteXYComm_AT (CRemoteXYStream *_serial, uint16_t _sendByteMax) : CRemoteXYComm () {
130 | serial = _serial;
131 | serial->setReadByteListener (this);
132 | sendByteMax = _sendByteMax;
133 | receiveBufferIndex=0;
134 |
135 | ipdSize = 0;
136 | lastAnswerTime = millis ();
137 |
138 | server = NULL;
139 | clients = NULL;
140 | availableClientID = -1;
141 | clientConnectingID = REMOTEXYCOMM_AT__NO_CHANNEL;
142 | detected = 0; // ???
143 |
144 |
145 | commandDelay = 0;
146 | commandIdentifier = 0;
147 | commandListener = NULL;
148 | findModuleTryCount = 0;
149 | commandBlocking = 0;
150 | }
151 |
152 |
153 |
154 | private:
155 | void resultATcommand (uint8_t identifier, uint8_t result) {
156 | uint8_t id = identifier;
157 | if (result !=AT_RESULT_MESSAGE) {
158 | commandResult = result;
159 | commandDelay = 0;
160 | commandIdentifier = 0;
161 | }
162 |
163 | if (id == AT_ID_FINDMODULE) {
164 | if (result == AT_RESULT_OK) {
165 | findModuleTryCount = 0;
166 | moduleFound ();
167 | }
168 | }
169 | else if (id == AT_ID_TESTMODULE) {
170 | if (result == AT_RESULT_MESSAGE) {
171 | if (strcmpReceiveBuffer (AT_MESSAGE_AT)==0) haveEcho = 1;
172 | }
173 | else if (result == AT_RESULT_OK) {
174 | if (haveEcho) moduleLost ();
175 |
176 | }
177 | else moduleLost ();
178 | }
179 | else {
180 | commandATListener (id, result);
181 | if (commandListener) commandListener (id, result);
182 | }
183 | }
184 |
185 |
186 | private:
187 | void serialWrite (const char *p) {
188 | while (*p) {
189 | serial->write (*p++);
190 | }
191 | }
192 |
193 |
194 | public:
195 | uint8_t readyATCommand () {
196 | if ((commandIdentifier) || (ipdSize) || (commandBlocking)) return 0;
197 | return 1;
198 | }
199 |
200 | public:
201 | void setATCommandListener (void (*listener)(uint8_t, uint8_t)) {
202 | commandListener = listener;
203 | }
204 |
205 | public:
206 | void setATTimeOut (uint32_t timeOut) {
207 | commandDelay = timeOut;
208 | }
209 |
210 | public:
211 | uint8_t getATResult () {
212 | return commandResult;
213 | }
214 |
215 |
216 | private:
217 | void sendArgPtr (const char * p, va_list *argptr) {
218 | if (p) {
219 | while (p) {
220 | serialWrite (p);
221 | #if defined(REMOTEXY__DEBUGLOG)
222 | RemoteXYDebugLog.writeOutput (p);
223 | #endif
224 | p=va_arg(*argptr,char*);
225 | }
226 | serialWrite ("\r\n");
227 | #if defined(REMOTEXY__DEBUGLOG)
228 | RemoteXYDebugLog.writeInputNewString ();
229 | #endif
230 | }
231 | commandTimeOut = millis();
232 | if (commandDelay == 0) commandDelay = REMOTEXYCOMM_AT__COMMAND_TIMEOUT;
233 | commandResult = 0;
234 | }
235 |
236 | // not blocking funktion, use:
237 | // for children class - virtual commandATListener (identifier, result)
238 | // for static function - setATListener (func)
239 | // result:
240 | // 0 - command did not send
241 | // 1 - command sent
242 | public:
243 | uint8_t sendATCommand (uint8_t identifier, const char * command, ...) {
244 | if (!readyATCommand ()) {
245 | commandDelay = 0;
246 | return 0;
247 | }
248 | va_list argptr;
249 | va_start (argptr, command);
250 | sendArgPtr (command, &argptr);
251 | va_end(argptr);
252 | commandIdentifier = identifier;
253 | return 1;
254 | }
255 |
256 |
257 | // blocking funktion
258 | // result: AT_RESULT_XXXXX
259 | public:
260 | uint8_t sendATCommandForResult (const char * command, ...) {
261 | if (!readyATCommand ()) {
262 | commandDelay = 0;
263 | return AT_RESULT_BUSY;
264 | }
265 | va_list argptr;
266 | va_start (argptr, command);
267 | sendArgPtr (command, &argptr);
268 | va_end(argptr);
269 |
270 | commandIdentifier = AT_ID_BLOCKING;
271 | commandBlocking = 1;
272 | while (commandResult == 0) {
273 | if (millis() - commandTimeOut > commandDelay) {
274 | resultATcommand (commandIdentifier, AT_RESULT_TIMEOUT);
275 | }
276 | else serial->handler ();
277 | }
278 | commandBlocking = 0;
279 | return commandResult;
280 | }
281 |
282 |
283 | public:
284 | uint8_t waitATResult () {
285 | return sendATCommandForResult (NULL, NULL);
286 | }
287 |
288 |
289 | public:
290 | void readByte (uint8_t byte) override {
291 |
292 | if (ipdSize) {
293 | ipdSize--;
294 | if (ipdClient) {
295 | ipdClient->notifyReadByteListener (byte);
296 | }
297 | #if defined(REMOTEXY__DEBUGLOG)
298 | if (ipdSize == 0) RemoteXYDebugLog.writeInputNewString ();
299 | #endif
300 | return;
301 | }
302 |
303 | if (byte==10) return;
304 | #if defined(REMOTEXY__DEBUGLOG)
305 | if (byte==13) RemoteXYDebugLog.writeInputNewString ();
306 | else RemoteXYDebugLog.writeInputChar (byte);
307 | #endif
308 | if (byte==13) {
309 | lastAnswerTime = millis ();
310 | receiveBuffer[receiveBufferIndex]=0;
311 | if (receiveBufferIndex == 0) return;
312 | receiveBufferIndex=0;
313 |
314 | if (strcmpReceiveBuffer (AT_MESSAGE_CONNECT)==0) { // new client
315 | uint8_t id = getATParamInt(0);
316 | if (id != clientConnectingID) {
317 | availableClientID = id;
318 | if (server) server->notifyClientAvailableListener ();
319 | }
320 | return;
321 | }
322 | if (strcmpReceiveBuffer (AT_MESSAGE_CLOSED)==0) { clientClosed (); return; } // client closed
323 | if (strcmpReceiveBuffer (AT_MESSAGE_CONNECT_FAIL)==0) { clientClosed (); return; } // client closed
324 | if (strcmpReceiveBuffer (AT_MESSAGE_READY)==0) {
325 | if (commandIdentifier) resultATcommand (commandIdentifier, AT_RESULT_TIMEOUT);
326 | moduleReset ();
327 | return;
328 | }
329 | if (handleATMessage ()) return;
330 | if (commandIdentifier) {
331 | if (strcmpReceiveBuffer (AT_ANSWER_OK)==0) resultATcommand (commandIdentifier, AT_RESULT_OK);
332 | else if (strcmpReceiveBuffer (AT_ANSWER_SEND_OK)==0) resultATcommand (commandIdentifier, AT_RESULT_SEND_OK);
333 | else if (strcmpReceiveBuffer (AT_ANSWER_ERROR)==0) resultATcommand (commandIdentifier, AT_RESULT_ERROR);
334 | else if (strcmpReceiveBuffer (AT_ANSWER_FAIL)==0) resultATcommand (commandIdentifier, AT_RESULT_FAIL);
335 | else if (strcmpReceiveBuffer (AT_ANSWER_BUSY)==0) resultATcommand (commandIdentifier, AT_RESULT_BUSY);
336 | else if (strcmpReceiveBuffer (AT_ANSWER_SEND_FAIL)==0) resultATcommand (commandIdentifier, AT_RESULT_SEND_FAIL);
337 | else resultATcommand (commandIdentifier, AT_RESULT_MESSAGE);
338 | return;
339 | }
340 | }
341 | else {
342 | if ((byte>0x60) && (byte<=0x7a)) byte-=0x20;
343 | if (receiveBufferIndexid == ipdId) && (p->_connected)) break;
357 | p = p->next;
358 | }
359 | ipdClient = p;
360 | return;
361 | }
362 | }
363 | else if ((byte=='>') && (receiveBufferIndex==1)) {
364 | receiveBufferIndex = 0;
365 | resultATcommand (commandIdentifier, AT_RESULT_SEND_READY);
366 | }
367 | else if ((byte==' ') && (receiveBufferIndex==1)) {
368 | receiveBufferIndex = 0;
369 | }
370 | }
371 | }
372 |
373 |
374 |
375 | public:
376 | void handler () override { // override CRemoteXYComm
377 |
378 | serial->handler ();
379 |
380 | if (!ipdSize) {
381 | if (commandIdentifier) {
382 | if (millis() - commandTimeOut > commandDelay) {
383 | resultATcommand (commandIdentifier, AT_RESULT_TIMEOUT);
384 | }
385 | }
386 | else if (findModuleTryCount) {
387 | if (millis() - lastAnswerTime > REMOTEXYCOMM_AT__COMMAND_TIMEOUT) {
388 | findModuleTryCount--;
389 | if (findModuleTryCount == 0) {
390 | #if defined(REMOTEXY__DEBUGLOG)
391 | RemoteXYDebugLog.write ("Мodule does not respond to AT commands");
392 | #endif
393 | findModuleTryCount = 10;
394 | }
395 | lastAnswerTime = millis ();
396 | sendATCommand (AT_ID_FINDMODULE, AT_MESSAGE_AT, NULL);
397 | }
398 | }
399 | else {
400 | if (millis() - lastAnswerTime > REMOTEXYCOMM_AT__TEST_TIMEOUT) {
401 | haveEcho = 0;
402 | if (sendATCommand (AT_ID_TESTMODULE, AT_MESSAGE_AT, NULL)) {
403 | lastAnswerTime = millis();
404 | }
405 | }
406 | }
407 | }
408 | }
409 |
410 |
411 | private:
412 | void clientClosed () {
413 | uint8_t id = getATParamInt(0);
414 | if (availableClientID == id) availableClientID = -1;
415 | else {
416 | CRemoteXYClient_AT_Proto * p = clients;
417 | while (p) {
418 | if ((p->id == id) && (p->_connected)) {
419 | p->_connected = 0;
420 | //return;
421 | }
422 | p = p->next;
423 | }
424 | }
425 | }
426 |
427 | public:
428 | uint8_t server_available (CRemoteXYClient_AT_Proto * client) {
429 | if (availableClientID >= 0) {
430 | client->id = availableClientID;
431 | client->_connected = 1;
432 | availableClientID = -1;
433 | return 1;
434 | }
435 | return 0;
436 | }
437 |
438 | public:
439 | uint8_t client_connect (CRemoteXYClient_AT_Proto * client, const char *host, uint16_t port) {
440 | char sport[6];
441 | char sid[2];
442 | int8_t i;
443 | CRemoteXYClient_AT_Proto * p;
444 | if (client->_connected) client_stop (client);
445 | clientConnectingID = REMOTEXYCOMM_AT__NO_CHANNEL;
446 | for (i=3; i>=0; i--) {
447 | p = clients;
448 | while (p) {
449 | if ((p->_connected) && (client->id == i)) break;
450 | p=p->next;
451 | }
452 | if (!p) {
453 | clientConnectingID = i;
454 | break;
455 | }
456 | }
457 | if (clientConnectingID == REMOTEXYCOMM_AT__NO_CHANNEL) return 0;
458 | rxy_itos (port, sport);
459 | *sid=clientConnectingID+0x30;
460 | *(sid+1)=0;
461 | setATTimeOut (REMOTEXYCOMM_AT__CONNECT_TIMEOUT);
462 | uint8_t res = sendATCommandForResult (AT_MESSAGE_CIPSTART, sid, ",\"TCP\",\"", host,"\",", sport,NULL);
463 | i = clientConnectingID;
464 | clientConnectingID = REMOTEXYCOMM_AT__NO_CHANNEL;
465 | if (res != AT_RESULT_OK) return 0;
466 | client->id = i;
467 | client->_connected = 1;
468 | return 1;
469 | }
470 |
471 | public:
472 | void client_stop (CRemoteXYClient_AT_Proto * client) {
473 | if (client->_connected) {
474 | client->_connected = 0;
475 | char s[2];
476 | *s=client->id+0x30;
477 | *(s+1) = 0;
478 | sendATCommandForResult (AT_MESSAGE_CIPCLOSE,s,NULL);
479 | }
480 | }
481 |
482 | public:
483 | void client_startWrite (CRemoteXYClient_AT_Proto * client, uint16_t size) {
484 | if (client->_connected) {
485 | char s[8];
486 | sendByteSize = size;
487 | if (sendByteSize > sendByteMax) sendByteSize = sendByteMax;
488 | sendByteNext = size - sendByteSize;
489 |
490 | rxy_itos (sendByteSize, s+2);
491 | *s=client->id+0x30;
492 | *(s+1)=',';
493 | #if defined(REMOTEXY__DEBUGLOG)
494 | RemoteXYDebugLog.writeInputNewString ();
495 | #endif
496 | uint8_t res = sendATCommandForResult (AT_MESSAGE_CIPSEND,s,NULL);
497 | if (res == AT_RESULT_OK) res = waitATResult ();
498 | if (res == AT_RESULT_SEND_READY) {
499 | #if defined(REMOTEXY__DEBUGLOG)
500 | RemoteXYDebugLog.writeAdd (" *send ");
501 | RemoteXYDebugLog.writeAdd (sendByteSize);
502 | RemoteXYDebugLog.writeAdd (" bytes*");
503 | #endif
504 | return;
505 | }
506 | sendByteSize = 0;
507 | }
508 | }
509 |
510 | public:
511 | void client_write (CRemoteXYClient_AT_Proto * client, uint8_t byte) {
512 | if (sendByteSize) {
513 | serial->write (byte);
514 | sendByteSize--;
515 | if (sendByteSize == 0) {
516 | setATTimeOut (REMOTEXYCOMM_AT__SEND_TIMEOUT);
517 | if (waitATResult () == AT_RESULT_SEND_OK) {
518 | if (sendByteNext) client_startWrite (client, sendByteNext);
519 | }
520 | }
521 | }
522 | }
523 |
524 |
525 |
526 |
527 | public:
528 | void findModule () {
529 | findModuleTryCount=10;
530 | lastAnswerTime = millis ();
531 | }
532 |
533 |
534 | protected:
535 | uint8_t strcmpReceiveBuffer (const char * temp) {
536 | uint8_t k = 0;
537 | char * str = receiveBuffer;
538 | while (*temp) {
539 | if (!*str) return 1;
540 | switch (*temp) {
541 | case '?':
542 | params[k]=str;
543 | paramsLength[k]=1;
544 | temp++;
545 | str++;
546 | k++;
547 | break;
548 | case '*':
549 | params[k]=str;
550 | paramsLength[k]=0;
551 | temp++;
552 | while (*str!=*temp) {
553 | if (!*str++) return 1;
554 | paramsLength[k]++;
555 | }
556 | k++;
557 | break;
558 | default:
559 | if (*(str++)!=*(temp++)) return 1;
560 | break;
561 | }
562 | }
563 | if (*str) return 1;
564 | return 0;
565 | }
566 |
567 | protected:
568 | uint16_t getATParamInt (uint8_t k) {
569 | uint16_t res = 0;
570 | char * p=params[k];
571 | uint8_t i=paramsLength[k];
572 | while (i--) res = res*10+(*p++)-'0';
573 | return res;
574 | }
575 |
576 | public:
577 | void registerClient (CRemoteXYClient_AT_Proto * client) {
578 | client->next = clients;
579 | clients = client;
580 | }
581 |
582 | public:
583 | void removeClient (CRemoteXYClient_AT_Proto * client) {
584 | CRemoteXYClient_AT_Proto ** pclient = &clients;
585 | while (*pclient) {
586 | if (*pclient == client) {
587 | if ((*pclient)->_connected) client_stop (*pclient);
588 | *pclient = client->next;
589 | return;
590 | }
591 | pclient = &((*pclient)->next);
592 | }
593 | }
594 |
595 |
596 | };
597 |
598 |
599 | class CRemoteXYServer_AT : public CRemoteXYServer {
600 |
601 |
602 | protected:
603 | CRemoteXYComm_AT * comm;
604 | uint16_t port;
605 |
606 | public:
607 | CRemoteXYServer_AT (CRemoteXYComm_AT * _comm, uint16_t _port) {
608 | comm = _comm;
609 | port = _port;
610 | comm->server = this;
611 | }
612 |
613 | ~CRemoteXYServer_AT () {
614 | if (comm) comm->server = NULL;
615 | }
616 |
617 |
618 | public:
619 | uint8_t available (CRemoteXYClient * client) override {
620 | return comm->server_available ((CRemoteXYClient_AT_Proto *)client);
621 | }
622 |
623 | uint8_t begin () override {
624 | char sport[6];
625 | rxy_itos (port, sport);
626 | if (comm->sendATCommandForResult ("AT+CIPSERVER=1,", sport, NULL) != AT_RESULT_OK) return 0;
627 | if (comm->sendATCommandForResult ("AT+CIPSTO=30", NULL) != AT_RESULT_OK) return 0;
628 | return 1;
629 | }
630 |
631 | void stop () override {
632 | comm->sendATCommandForResult ("AT+CIPSERVER=0", NULL);
633 | }
634 |
635 | };
636 |
637 |
638 | class CRemoteXYClient_AT : public CRemoteXYClient_AT_Proto {
639 |
640 | public:
641 | CRemoteXYClient_AT (CRemoteXYComm_AT * _comm) {
642 | comm = _comm;
643 | _connected = 0;
644 | comm->registerClient (this);
645 | }
646 |
647 | ~CRemoteXYClient_AT () {
648 | if (comm) comm->removeClient (this);
649 | }
650 |
651 | public:
652 | uint8_t connect (const char *host, uint16_t port) override {
653 | if (comm) return comm->client_connect (this, host, port);
654 | return 0;
655 | }
656 |
657 | public:
658 | uint8_t connected () override {
659 | return _connected;
660 | }
661 |
662 | public:
663 | void stop () override {
664 | if (comm) comm->client_stop (this);
665 | }
666 |
667 | void startWrite (uint16_t size) override {
668 | if (comm) comm->client_startWrite (this, size);
669 | }
670 |
671 | void write (uint8_t byte) override {
672 | if (comm) comm->client_write (this, byte);
673 | }
674 |
675 | };
676 |
677 |
678 |
679 |
680 |
681 | #endif // RemoteXYComm_AT_h
682 |
--------------------------------------------------------------------------------
/src/RemoteXYComm_ESP8266.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYComm_ESP8266_h
2 | #define RemoteXYComm_ESP8266_h
3 |
4 | #include "RemoteXYDebugLog.h"
5 | #include "RemoteXYComm_AT.h"
6 |
7 | #define REMOTEXYCOMM_ESP8266__SERVER_TIMEOUT 10000
8 | #define REMOTEXYCOMM_ESP8266__WIFICONNECT_TIMEOUT 30000
9 |
10 | #define REMOTEXYCOMM_ESP8266__ID_WIFICONNECT 1
11 |
12 | #define REMOTEXYCOMM_ESP8266__MAX_SEND_BYTE_SIZE 2048
13 |
14 | const char * AT_MESSAGE_WIFI_DISCONNECT = "WIFI DISCONNECT";
15 |
16 |
17 | class CRemoteXYComm_ESP8266_Proto : public CRemoteXYComm_AT {
18 |
19 | protected:
20 | const char * wifiSsid;
21 | const char * wifiPassword;
22 | enum { Search, Reset, SearchAfterReset, Init, WaitWiFi, WaitReconnect, Configured } state;
23 | uint32_t timeOut;
24 |
25 | public:
26 | CRemoteXYComm_ESP8266_Proto (CRemoteXYStream *_serial, const char * _wifiSsid, const char * _wifiPassword) : CRemoteXYComm_AT (_serial, REMOTEXYCOMM_ESP8266__MAX_SEND_BYTE_SIZE) {
27 | wifiSsid = _wifiSsid;
28 | wifiPassword = _wifiPassword;
29 | state = Search;
30 | findModule ();
31 | }
32 |
33 |
34 | void moduleFound () override {
35 | if ((state == Reset) || (state == SearchAfterReset)) moduleReset ();
36 | else {
37 | state = Reset;
38 | timeOut = millis ();
39 | sendATCommandForResult ("AT+RST",NULL); // reset module
40 | }
41 | }
42 |
43 | protected:
44 | void moduleLost () override {
45 | state = Search;
46 | findModule ();
47 | }
48 |
49 |
50 |
51 | uint8_t configured () override {
52 | return (state == Configured);
53 | };
54 |
55 | virtual CRemoteXYServer * createServer (uint16_t _port) override {
56 | if (!server) {
57 | server = new CRemoteXYServer_AT (this, _port);
58 | return server;
59 | }
60 | return NULL;
61 | }
62 |
63 | public:
64 | CRemoteXYClient * newClient () override {
65 | return new CRemoteXYClient_AT (this);
66 | }
67 |
68 | };
69 |
70 | class CRemoteXYComm_ESP8266 : public CRemoteXYComm_ESP8266_Proto {
71 |
72 | public:
73 | CRemoteXYComm_ESP8266 (CRemoteXYStream *_serial, const char * _wifiSsid, const char * _wifiPassword) : CRemoteXYComm_ESP8266_Proto (_serial, _wifiSsid, _wifiPassword) {
74 | }
75 |
76 | protected:
77 | void moduleReset () override {
78 | if (!initModule ()) {
79 | state = Search;
80 | findModule ();
81 | }
82 | }
83 |
84 |
85 |
86 | private:
87 | uint8_t initModule () {
88 | state = Init;
89 | if (sendATCommandForResult ("ATE0",NULL) != AT_RESULT_OK) return 0;
90 | if (sendATCommandForResult ("AT+CWMODE=1",NULL) != AT_RESULT_OK) return 0;
91 | if (sendATCommandForResult ("AT+CWQAP",NULL) != AT_RESULT_OK) return 0;
92 | if (sendATCommandForResult ("AT+CWDHCP=1,1",NULL) != AT_RESULT_OK) return 0;
93 | if (sendATCommandForResult ("AT+CIPMODE=0",NULL) != AT_RESULT_OK) return 0;
94 | if (sendATCommandForResult ("AT+CIPMUX=1",NULL) != AT_RESULT_OK) return 0;
95 | beginWiFi ();
96 | return 1;
97 | }
98 |
99 | private:
100 | void beginWiFi () {
101 | state = Init;
102 | setATTimeOut (REMOTEXYCOMM_ESP8266__WIFICONNECT_TIMEOUT);
103 | if (sendATCommand (REMOTEXYCOMM_ESP8266__ID_WIFICONNECT, "AT+CWJAP=\"",wifiSsid,"\",\"",wifiPassword,"\"",NULL)) state = WaitWiFi;
104 | }
105 |
106 |
107 | protected:
108 | void commandATListener (uint8_t identifier, uint8_t result) override {
109 | if (identifier == REMOTEXYCOMM_ESP8266__ID_WIFICONNECT) {
110 | if (result == AT_RESULT_OK) {
111 | #if defined(REMOTEXY__DEBUGLOG)
112 | sendATCommandForResult ("AT+CIPSTA?",NULL);
113 | #endif
114 | state = Configured;
115 | }
116 | else {
117 | state = WaitReconnect;
118 | timeOut = millis();
119 | }
120 | }
121 | }
122 |
123 | virtual void handler () override { // override CRemoteXYComm_AT
124 | CRemoteXYComm_AT::handler ();
125 | if (state == Reset) {
126 | if (millis() - timeOut > 5000) {
127 | state = SearchAfterReset;
128 | findModule ();
129 | }
130 | }
131 | else if (state == Init) beginWiFi ();
132 | else if (state == WaitReconnect) {
133 | if (millis() - timeOut > REMOTEXYCOMM_ESP8266__WIFICONNECT_TIMEOUT) beginWiFi ();
134 | }
135 | }
136 |
137 | uint8_t handleATMessage () override { // override CRemoteXYComm_AT
138 | if (strcmpReceiveBuffer (AT_MESSAGE_WIFI_DISCONNECT)==0) {
139 | if (state == Configured) state = Init;
140 | return 1;
141 | }
142 | return 0;
143 | }
144 |
145 |
146 | };
147 |
148 |
149 | class CRemoteXYComm_ESP8266Point : public CRemoteXYComm_ESP8266_Proto {
150 |
151 | public:
152 | CRemoteXYComm_ESP8266Point (CRemoteXYStream *_serial, const char * _wifiSsid, const char * _wifiPassword) : CRemoteXYComm_ESP8266_Proto (_serial, _wifiSsid, _wifiPassword) {
153 | }
154 |
155 | protected:
156 | void moduleReset () override {
157 | initModule ();
158 | if (state != Configured) {
159 | state = Search;
160 | findModule ();
161 | }
162 | }
163 |
164 | private:
165 | void initModule () {
166 | state = Init;
167 | if (sendATCommandForResult ("ATE0",NULL) != AT_RESULT_OK) return;
168 | if (sendATCommandForResult ("AT+CWMODE=2",NULL) != AT_RESULT_OK) return;
169 | if (sendATCommandForResult ("AT+CWDHCP=0,1",NULL) != AT_RESULT_OK) return;
170 |
171 | char crypt[2] = {*wifiPassword?'4':'0',0};
172 | setATTimeOut (5000);
173 | if (sendATCommandForResult ("AT+CWSAP=\"",wifiSsid,"\",\"",wifiPassword,"\",10,",crypt,NULL) != AT_RESULT_OK) return;
174 | if (sendATCommandForResult ("AT+CIPMODE=0",NULL) != AT_RESULT_OK) return;
175 | if (sendATCommandForResult ("AT+CIPMUX=1",NULL) != AT_RESULT_OK) return;
176 | state = Configured;
177 | }
178 |
179 | virtual void handler () override {
180 | CRemoteXYComm_AT::handler ();
181 | if (state == Reset) {
182 | if (millis() - timeOut > 5000) {
183 | state = SearchAfterReset;
184 | findModule ();
185 | }
186 | }
187 | }
188 |
189 | };
190 |
191 |
192 |
193 |
194 | #endif // RemoteXYComm_ESP8266_h
195 |
--------------------------------------------------------------------------------
/src/RemoteXYComm_Ethernet.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYComm_Ethernet_h
2 | #define RemoteXYComm_Ethernet_h
3 |
4 |
5 | #if defined (ethernet_h_)
6 |
7 | #include "RemoteXYDebugLog.h"
8 | #include "RemoteXYComm.h"
9 | #include "RemoteXYFunc.h"
10 |
11 |
12 | #define REMOREXYCOMM_ETHERNET__SEND_BUFFER_SIZE 32
13 |
14 | class CRemoteXYClient_Ethernet : public CRemoteXYClient {
15 | public:
16 | EthernetClient client;
17 |
18 | uint8_t sendBuffer[REMOREXYCOMM_ETHERNET__SEND_BUFFER_SIZE];
19 | uint16_t sendBufferCount;
20 | uint16_t sendBytesAvailable;
21 |
22 | public:
23 | uint8_t connect (const char *host, uint16_t port) override {
24 | return client.connect(host, port);
25 | };
26 |
27 | public:
28 | uint8_t connected () override {
29 | return client.connected();
30 | };
31 |
32 | public:
33 | void stop () override {
34 | client.stop ();
35 | };
36 |
37 | public:
38 | void handler () override {
39 | while (client.available ()) notifyReadByteListener (client.read ());
40 | }
41 |
42 |
43 |
44 | public:
45 | void startWrite (uint16_t len) override {
46 | sendBytesAvailable = len;
47 | sendBufferCount = 0;
48 | }
49 |
50 | public:
51 | void write (uint8_t b) override {
52 | sendBuffer[sendBufferCount++] = b;
53 | sendBytesAvailable--;
54 | if ((sendBufferCount == REMOREXYCOMM_ETHERNET__SEND_BUFFER_SIZE) || (sendBytesAvailable==0)) {
55 | client.write (sendBuffer, sendBufferCount);
56 | sendBufferCount=0;
57 | }
58 | }
59 |
60 |
61 | };
62 |
63 | #if defined (ESP32)
64 | class EthernetServerESP32: public EthernetServer {
65 | public:
66 | EthernetServerESP32 (uint16_t port) : EthernetServer (port) {}
67 | void begin(uint16_t port=0) {}
68 | };
69 | #endif
70 |
71 | class CRemoteXYServer_Ethernet : public CRemoteXYServer {
72 | private:
73 | EthernetServer * server;
74 | uint8_t soketConnectArr[MAX_SOCK_NUM];
75 |
76 | public:
77 | CRemoteXYServer_Ethernet (uint16_t _port) {
78 | #if defined (ESP32)
79 | server = new EthernetServerESP32 (_port);
80 | #else
81 | server = new EthernetServer (_port);
82 | #endif
83 | for (uint8_t i = 0; i < MAX_SOCK_NUM; i++) soketConnectArr[i] = 0;
84 | }
85 |
86 |
87 | public:
88 | virtual uint8_t begin () override {
89 | server->begin ();
90 | return 1;
91 | }
92 |
93 |
94 | uint8_t available (CRemoteXYClient * client) override {
95 | EthernetClient cl;
96 | uint8_t i;
97 | for (i = 0; i < MAX_SOCK_NUM; i++) {
98 | cl = EthernetClient (i);
99 | if (!cl.connected ()) soketConnectArr[i] = 0;
100 | }
101 | cl = server->available ();
102 | if (cl.connected ()) {
103 | i = cl.getSocketNumber();
104 | if (iclient = cl;
108 | return 1;
109 | }
110 | }
111 | }
112 | return 0;
113 | }
114 |
115 | };
116 |
117 |
118 | class CRemoteXYComm_Ethernet : public CRemoteXYComm {
119 |
120 | private:
121 | uint8_t mac[6];
122 | enum {NoHardware, LinkDetecting, Work} state;
123 | uint32_t timeout;
124 |
125 |
126 | public:
127 | CRemoteXYComm_Ethernet (const char * macAddress) : CRemoteXYComm () {
128 | rxy_getMacAddr (macAddress, mac);
129 |
130 | #if defined(REMOTEXY__DEBUGLOG)
131 | RemoteXYDebugLog.write("Ethernet begin ...");
132 | #endif
133 |
134 | Ethernet.begin(mac, 1000);
135 |
136 | if (Ethernet.hardwareStatus() == EthernetNoHardware) {
137 | state = NoHardware;
138 | #if defined(REMOTEXY__DEBUGLOG)
139 | RemoteXYDebugLog.write("Ethernet module was not found");
140 | #endif
141 | }
142 | else {
143 | state = LinkDetecting;
144 | #if defined(REMOTEXY__DEBUGLOG)
145 | if (!linkON ()) {
146 | RemoteXYDebugLog.write("Ethernet link OFF");
147 | }
148 | #endif
149 | }
150 | timeout = millis ();
151 | }
152 |
153 |
154 | private:
155 | uint8_t linkON () {
156 | return 1;
157 | if (Ethernet.hardwareStatus () == EthernetW5100) {
158 | if (uint32_t(Ethernet.localIP()) != 0) return 1;
159 | }
160 | else {
161 | if (Ethernet.linkStatus () == LinkON) return 1;
162 | }
163 | return 0;
164 | }
165 |
166 |
167 | public:
168 | void handler () override {
169 |
170 | if (state == NoHardware) return;
171 |
172 | if (linkON ()) {
173 | if (state == LinkDetecting) {
174 | #if defined(REMOTEXY__DEBUGLOG)
175 | RemoteXYDebugLog.write ("Ethernet link ON");
176 | RemoteXYDebugLog.write("IP: ");
177 | RemoteXYDebugLog.serial->print(Ethernet.localIP());
178 | #endif
179 | state = Work;
180 | }
181 | timeout = millis ();
182 | }
183 | else { // LinkOFF
184 | if (state == Work) {
185 | state = LinkDetecting;
186 | #if defined(REMOTEXY__DEBUGLOG)
187 | RemoteXYDebugLog.write ("Ethernet link OFF");
188 | #endif
189 | }
190 | else {
191 | if (millis () - timeout > 5000) {
192 | Ethernet.begin(mac, 100);
193 | timeout = millis ();
194 | }
195 | }
196 | }
197 | }
198 |
199 |
200 | public:
201 | uint8_t configured () override {
202 | if (state == Work) return 1;
203 | return 0;
204 | }
205 |
206 | public:
207 | CRemoteXYServer * createServer (uint16_t _port) override {
208 | return new CRemoteXYServer_Ethernet (_port);
209 | }
210 |
211 |
212 | CRemoteXYClient * newClient () override {
213 | return new CRemoteXYClient_Ethernet ();
214 | }
215 |
216 | };
217 |
218 |
219 | #endif // ethernet_h_
220 |
221 | #endif //RemoteXYComm_Ethernet_h
--------------------------------------------------------------------------------
/src/RemoteXYComm_WiFi.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYComm_WiFi_h
2 | #define RemoteXYComm_WiFi_h
3 |
4 | #include "RemoteXYDebugLog.h"
5 | #include "RemoteXYComm.h"
6 |
7 | #if defined (WiFi_h)
8 |
9 | #if defined (ESP8266) || defined (ESP32)
10 | #define REMOREXYCOMM_WIFI__SEND_BUFFER_SIZE 256
11 | #else // arduino shield
12 | #define REMOREXYCOMM_WIFI__SEND_BUFFER_SIZE 64
13 | #endif
14 |
15 |
16 |
17 |
18 |
19 | class CRemoteXYClient_WiFi : public CRemoteXYClient {
20 | public:
21 | WiFiClient client;
22 |
23 | uint8_t sendBuffer[REMOREXYCOMM_WIFI__SEND_BUFFER_SIZE];
24 | uint16_t sendBufferCount;
25 | uint16_t sendBytesAvailable;
26 |
27 | public:
28 | uint8_t connect (const char *host, uint16_t port) override {
29 | return client.connect(host, port);
30 | };
31 |
32 | public:
33 | uint8_t connected () override {
34 | return client.connected();
35 | };
36 |
37 | public:
38 | void stop () override {
39 | client.stop ();
40 | };
41 |
42 | public:
43 | void handler () override {
44 | while (client.available ()) notifyReadByteListener (client.read ());
45 | }
46 |
47 |
48 | public:
49 | void startWrite (uint16_t len) override {
50 | sendBytesAvailable = len;
51 | sendBufferCount = 0;
52 | }
53 |
54 | public:
55 | void write (uint8_t b) override {
56 | sendBuffer[sendBufferCount++] = b;
57 | sendBytesAvailable--;
58 | if ((sendBufferCount == REMOREXYCOMM_WIFI__SEND_BUFFER_SIZE) || (sendBytesAvailable==0)) {
59 | client.write (sendBuffer, sendBufferCount);
60 | sendBufferCount=0;
61 | }
62 | }
63 |
64 | };
65 |
66 | class CRemoteXYServer_WiFi : public CRemoteXYServer {
67 | private:
68 | WiFiServer * server;
69 |
70 | public:
71 | CRemoteXYServer_WiFi (uint16_t _port) {
72 | server = new WiFiServer (_port);
73 | }
74 |
75 |
76 | public:
77 | virtual uint8_t begin () override {
78 | server->begin ();
79 | return 1;
80 | }
81 |
82 |
83 | void stop () override {
84 | #if defined (ESP8266) || defined (ESP32)
85 | server->stop ();
86 | #endif
87 | }
88 |
89 |
90 |
91 | uint8_t available (CRemoteXYClient * client) override {
92 | #if defined (ESP8266) || defined (ESP32)
93 | if (!server->hasClient()) return 0;
94 | #endif
95 | WiFiClient cl = server->available ();
96 | if (cl) {
97 | if (cl.connected ()) {
98 | #if defined (ESP8266)
99 | cl.disableKeepAlive (); // remove memory leak
100 | #endif
101 | ((CRemoteXYClient_WiFi*) client)->client = cl;
102 | return 1;
103 | }
104 | }
105 | return 0;
106 | }
107 |
108 | };
109 |
110 |
111 | class CRemoteXYComm_WiFi : public CRemoteXYComm {
112 |
113 | private:
114 | char * wifiSsid;
115 | char * wifiPassword;
116 | uint8_t wifiStatus;
117 |
118 |
119 | public:
120 | CRemoteXYComm_WiFi (const char * _wifiSsid, const char * _wifiPassword) : CRemoteXYComm () {
121 | wifiSsid = (char *)_wifiSsid;
122 | wifiPassword = (char *)_wifiPassword;
123 |
124 |
125 | wifiStatus = WiFi.status();
126 |
127 | #if defined (ESP8266) || defined (ESP32)
128 |
129 | WiFi.disconnect();
130 | WiFi.softAPdisconnect(true);
131 | WiFi.mode(WIFI_STA);
132 |
133 | #else // NOT ESP
134 |
135 | if (wifiStatus == WL_NO_SHIELD) {
136 | #if defined(REMOTEXY__DEBUGLOG)
137 | RemoteXYDebugLog.write("WiFi module was not found");
138 | #endif
139 | return;
140 | }
141 |
142 | #endif // ESP
143 |
144 |
145 | #if defined(REMOTEXY__DEBUGLOG)
146 | RemoteXYDebugLog.write("Сonnecting to WiFi: ");
147 | RemoteXYDebugLog.writeAdd(wifiSsid);
148 | RemoteXYDebugLog.writeAdd(" ...");
149 | #endif
150 |
151 | WiFi.begin(wifiSsid, wifiPassword);
152 |
153 | #if defined (ESP8266) || defined (ESP32)
154 | WiFi.setAutoReconnect (true);
155 | #endif
156 |
157 | }
158 |
159 |
160 | void handler () override {
161 |
162 | uint8_t prev_wifiStatus = wifiStatus;
163 | wifiStatus = WiFi.status();
164 |
165 | if (wifiStatus == WL_CONNECTED) {
166 | if (prev_wifiStatus != WL_CONNECTED) {
167 | #if defined(REMOTEXY__DEBUGLOG)
168 | RemoteXYDebugLog.write ("WiFi connected");
169 | RemoteXYDebugLog.write ("IP: ");
170 | RemoteXYDebugLog.serial->print (WiFi.localIP());
171 | #endif
172 |
173 | }
174 | }
175 | else { // != WL_CONNECTED
176 | if (prev_wifiStatus == WL_CONNECTED) {
177 | #if defined(REMOTEXY__DEBUGLOG)
178 | RemoteXYDebugLog.write ("WiFi disconnected");
179 | #endif
180 | #if defined (ESP32)
181 | WiFi.disconnect();
182 | WiFi.mode(WIFI_STA);
183 | WiFi.begin(wifiSsid, wifiPassword);
184 | #endif
185 | }
186 | }
187 | }
188 |
189 |
190 | public:
191 | uint8_t configured () override {
192 | if (wifiStatus == WL_CONNECTED) return 1;
193 | return 0;
194 | }
195 |
196 | public:
197 | CRemoteXYServer * createServer (uint16_t _port) override {
198 | return new CRemoteXYServer_WiFi (_port);
199 | }
200 |
201 |
202 | CRemoteXYClient * newClient () override {
203 | return new CRemoteXYClient_WiFi ();
204 | }
205 |
206 | };
207 |
208 |
209 |
210 | class CRemoteXYComm_WiFiPoint : public CRemoteXYComm {
211 |
212 | uint8_t state;
213 |
214 | public:
215 | CRemoteXYComm_WiFiPoint (const char * _wifiSsid, const char * _wifiPassword) : CRemoteXYComm () {
216 |
217 |
218 | #if defined(REMOTEXY__DEBUGLOG)
219 | RemoteXYDebugLog.write("Creating WiFi point: ");
220 | RemoteXYDebugLog.writeAdd(_wifiSsid);
221 | RemoteXYDebugLog.writeAdd(" ...");
222 | #endif
223 |
224 | #if defined (ESP8266) || defined (ESP32)
225 |
226 | WiFi.mode(WIFI_AP);
227 | WiFi.softAP(_wifiSsid, _wifiPassword);
228 | state = 1;
229 | #if defined(REMOTEXY__DEBUGLOG)
230 | RemoteXYDebugLog.write("WiFi point created");
231 | RemoteXYDebugLog.write ("IP: ");
232 | RemoteXYDebugLog.serial->print (WiFi.softAPIP());
233 | #endif
234 |
235 | #elif defined (WiFiNINA_h) // WiFiNINA
236 |
237 | state = 0;
238 | if (WiFi.status() == WL_NO_SHIELD) {
239 | #if defined(REMOTEXY__DEBUGLOG)
240 | RemoteXYDebugLog.write("WiFi module was not found");
241 | #endif
242 | return;
243 | }
244 | if (WiFi.beginAP (_wifiSsid, _wifiPassword) != WL_AP_LISTENING) {
245 | #if defined(REMOTEXY__DEBUGLOG)
246 | RemoteXYDebugLog.write("WiFi module does not support AP mode");
247 | #endif
248 | return;
249 | }
250 | state = 1;
251 |
252 | #if defined(REMOTEXY__DEBUGLOG)
253 | RemoteXYDebugLog.write("WiFi point created");
254 | #endif
255 |
256 | #else // other boards not support AP mode
257 | state = 0;
258 | #if defined(REMOTEXY__DEBUGLOG)
259 | RemoteXYDebugLog.write("WiFi module does not support AP mode");
260 | #endif
261 |
262 | #endif // ESP
263 |
264 | }
265 |
266 | public:
267 | uint8_t configured () override {
268 | return state;
269 | }
270 |
271 |
272 | public:
273 | CRemoteXYServer * createServer (uint16_t _port) override {
274 | return new CRemoteXYServer_WiFi (_port);
275 | }
276 |
277 |
278 | CRemoteXYClient * newClient () override {
279 | return new CRemoteXYClient_WiFi ();
280 | }
281 |
282 | };
283 |
284 |
285 | #endif // WiFi_h
286 |
287 | #endif //RemoteXYComm_WiFi_h
--------------------------------------------------------------------------------
/src/RemoteXYConnection.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYConnection_h
2 | #define RemoteXYConnection_h
3 |
4 | #include "RemoteXYComm.h"
5 | #include "RemoteXYWire.h"
6 | #include "RemoteXYCloudServer.h"
7 |
8 | #define UNUSED(x) (void)(x)
9 |
10 | class CRemoteXYConnection {
11 |
12 | public:
13 | virtual void init (CRemoteXYData * _data);
14 |
15 | public:
16 | virtual void handler () {};
17 | virtual void handleWire (CRemoteXYWire * wire) {UNUSED (wire);};
18 | virtual void stopThreadListener (CRemoteXYWire * wire) {UNUSED (wire);};
19 |
20 | };
21 |
22 |
23 | class CRemoteXYConnectionComm : public CRemoteXYConnection {
24 | public:
25 | CRemoteXYConnectionComm * next;
26 | CRemoteXYComm * comm;
27 |
28 | public:
29 | CRemoteXYConnectionComm (CRemoteXYComm * _comm) {
30 | comm = _comm;
31 | }
32 |
33 | };
34 |
35 | #endif //RemoteXYConnection_h
--------------------------------------------------------------------------------
/src/RemoteXYConnectionCloud.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYConnectionCloud_h
2 | #define RemoteXYConnectionCloud_h
3 |
4 | #include "RemoteXYDebugLog.h"
5 | #include "RemoteXYConnection.h"
6 | #include "RemoteXYThread.h"
7 |
8 | #define REMOTEXY_CLOUDCLIENT_RETRY_TIMEOUT 20000
9 |
10 | class CRemoteXYConnectionCloud: public CRemoteXYConnectionComm, CRemoteXYCloudClientAvailableListener {
11 | public:
12 | uint16_t port;
13 | CRemoteXYCloudServer * cloudServer;
14 | const char * cloudHost;
15 | const char * cloudToken;
16 | CRemoteXYData * data;
17 | CRemoteXYClient * client;
18 | uint32_t timeOut;
19 |
20 | public:
21 | CRemoteXYConnectionCloud (CRemoteXYComm * _comm, const char * _cloudHost, uint16_t _port, const char * _cloudToken) : CRemoteXYConnectionComm (_comm) {
22 | port = _port;
23 | cloudHost = _cloudHost;
24 | cloudToken = _cloudToken;
25 | }
26 |
27 | public:
28 | void init (CRemoteXYData * _data) override {
29 | data = _data;
30 | cloudServer = new CRemoteXYCloudServer (data, cloudToken, this);
31 | client = comm->newClient ();
32 | timeOut = -REMOTEXY_CLOUDCLIENT_RETRY_TIMEOUT;
33 | }
34 |
35 | void handler () override {
36 |
37 | if (comm->configured ()) {
38 | if (cloudServer->running ()) {
39 | cloudServer->handler();
40 | timeOut = millis();
41 | }
42 | else { // not serverRunning
43 | if (millis() - timeOut > REMOTEXY_CLOUDCLIENT_RETRY_TIMEOUT) {
44 | #if defined(REMOTEXY__DEBUGLOG)
45 | RemoteXYDebugLog.write ("Connecting to cloud: ");
46 | RemoteXYDebugLog.writeAdd (cloudHost);
47 | RemoteXYDebugLog.writeAdd (" ");
48 | RemoteXYDebugLog.writeAdd (port);
49 | RemoteXYDebugLog.writeAdd (" ..");
50 | #endif
51 | if (client->connect (cloudHost, port)) {
52 | #if defined(REMOTEXY__DEBUGLOG)
53 | RemoteXYDebugLog.write ("Cloud server connected");
54 | #endif
55 | cloudServer->begin (client);
56 | }
57 | #if defined(REMOTEXY__DEBUGLOG)
58 | else {
59 | RemoteXYDebugLog.write ("Cloud server not available");
60 | }
61 | #endif
62 | timeOut = millis();
63 | }
64 | }
65 | }
66 | else cloudServer->stop ();
67 | if (!cloudServer->running ()) {
68 | if (client->connected ()) {
69 | client->stop ();
70 | }
71 | }
72 | }
73 |
74 | void clientAvailable (CRemoteXYWireCloud * cloudWire) override {
75 | if (CRemoteXYThread::runningCount (data) < REMOTEXY_MAX_CLIENTS) {
76 | CRemoteXYThread::startThread (data, this, cloudWire, 1);
77 | }
78 | else {
79 | cloudWire->stop ();
80 | #if defined(REMOTEXY__DEBUGLOG)
81 | RemoteXYDebugLog.write ("Client reject");
82 | #endif
83 | }
84 |
85 | }
86 |
87 |
88 | void handleWire (CRemoteXYWire * wire) override {
89 | if (cloudServer->running () && comm->configured ()) wire->handler ();
90 | else stopThreadListener (wire);
91 | }
92 |
93 | void stopThreadListener (CRemoteXYWire * wire) override {
94 | wire->stop ();
95 | }
96 |
97 |
98 |
99 | };
100 |
101 |
102 | #endif // RemoteXYConnectionCloud_h
--------------------------------------------------------------------------------
/src/RemoteXYConnectionServer.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYConnectionServer_h
2 | #define RemoteXYConnectionServer_h
3 |
4 | #include "RemoteXYDebugLog.h"
5 | #include "RemoteXYConnection.h"
6 | #include "RemoteXYWireStream.h"
7 | #include "RemoteXYThread.h"
8 |
9 |
10 |
11 | class CRemoteXYConnectionServer: public CRemoteXYConnectionComm, public CRemoteXYClientAvailableListener {
12 | public:
13 | uint16_t port;
14 | CRemoteXYData * data;
15 | CRemoteXYServer * server;
16 | CRemoteXYClient * clients;
17 | CRemoteXYWireStream * wires;
18 | uint8_t serverRunning;
19 |
20 |
21 | CRemoteXYConnectionServer (CRemoteXYComm * _comm, uint16_t _port = 0) : CRemoteXYConnectionComm (_comm) {
22 | port = _port;
23 | clients = NULL;
24 | server = comm->createServer (port);
25 | server->setClientAvailabListener (this);
26 | #if defined(REMOTEXY__DEBUGLOG)
27 | if (!server) {
28 | RemoteXYDebugLog.write ("Server was not created");
29 | }
30 | #endif
31 | serverRunning = 0;
32 | wires = NULL;
33 | }
34 |
35 | void init (CRemoteXYData * _data) {
36 | data = _data;
37 | }
38 |
39 | public:
40 | void handler () override {
41 | if (!server) return;
42 | if (comm->configured ()) {
43 | if (serverRunning) clientAvailable ();
44 | else {
45 | if (server->begin ()) {
46 | serverRunning=1;
47 | #if defined(REMOTEXY__DEBUGLOG)
48 | RemoteXYDebugLog.write ("Server opened on port ");
49 | RemoteXYDebugLog.writeAdd (port);
50 | #endif
51 | }
52 | #if defined(REMOTEXY__DEBUGLOG)
53 | else {
54 | RemoteXYDebugLog.write ("Server was not started");
55 | }
56 | #endif
57 | }
58 | }
59 | else {
60 | if (serverRunning) {
61 | server->stop ();
62 | serverRunning =0;
63 | }
64 | }
65 | }
66 |
67 | void clientAvailable () override {
68 | CRemoteXYClient * client = clients;
69 | while (client) {
70 | if (!client->connected ()) break;
71 | client = client->next;
72 | }
73 | if (!client) {
74 | client = comm->newClient ();
75 | client->next = clients;
76 | clients = client;
77 | }
78 | if (server->available (client)) {
79 |
80 | if (CRemoteXYThread::runningCount (data) < REMOTEXY_MAX_CLIENTS) {
81 | CRemoteXYWireStream * wire = wires;
82 | while (wire) {
83 | if (!wire->running()) break;
84 | wire = wire->next;
85 | }
86 | if (!wire) {
87 | wire = new CRemoteXYWireStream (data);
88 | wire->next = wires;
89 | wires = wire;
90 | }
91 | wire->begin (client);
92 | CRemoteXYThread::startThread (data, this, wire, 1);
93 | }
94 | else {
95 | client->stop ();
96 | #if defined(REMOTEXY__DEBUGLOG)
97 | RemoteXYDebugLog.write ("Client reject");
98 | #endif
99 | }
100 | }
101 |
102 | }
103 |
104 | void handleWire (CRemoteXYWire * wire) override {
105 | CRemoteXYClient * client = ((CRemoteXYWireStream*)wire)->getClient ();
106 | if (client) {
107 | if (client->connected () && serverRunning && comm->configured ()) wire->handler ();
108 | else stopThreadListener (wire);
109 | }
110 | }
111 |
112 | void stopThreadListener (CRemoteXYWire * wire) override {
113 | CRemoteXYClient * client = ((CRemoteXYWireStream*)wire)->getClient ();
114 | if (client) {
115 | client->stop ();
116 | wire->stop ();
117 | }
118 | }
119 |
120 |
121 |
122 | };
123 |
124 |
125 | #endif // RemoteXYConnectionServer_h
--------------------------------------------------------------------------------
/src/RemoteXYConnectionStream.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYConnectionStream_h
2 | #define RemoteXYConnectionStream_h
3 |
4 | #include "RemoteXYDebugLog.h"
5 | #include "RemoteXYConnection.h"
6 | #include "RemoteXYThread.h"
7 |
8 | class CRemoteXYConnectionStream: public CRemoteXYConnection {
9 | CRemoteXYStream * stream;
10 |
11 | public:
12 | CRemoteXYConnectionStream (CRemoteXYStream * _stream) {
13 | stream = _stream;
14 | }
15 |
16 | void init (CRemoteXYData * _data) override {
17 | CRemoteXYWireStream * wire = new CRemoteXYWireStream (_data);
18 | wire->begin (stream);
19 | CRemoteXYThread::startThread (_data, this, wire, 0);
20 | };
21 |
22 | void handleWire (CRemoteXYWire * wire) override {
23 | wire->handler ();
24 | };
25 |
26 | };
27 |
28 | #endif // CRemoteXYConnectionStream
--------------------------------------------------------------------------------
/src/RemoteXYDebugLog.h:
--------------------------------------------------------------------------------
1 | #ifndef _REMOTEXY_DEBUGLOG_H_
2 | #define _REMOTEXY_DEBUGLOG_H_
3 |
4 | #if defined(REMOTEXY__DEBUGLOG)
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #ifndef REMOTEXY__DEBUGLOG_SERIAL
11 | #define REMOTEXY__DEBUGLOG_SERIAL Serial
12 | #endif
13 | #ifndef REMOTEXY__DEBUGLOG_SPEED
14 | #define REMOTEXY__DEBUGLOG_SPEED 115200
15 | #endif
16 |
17 |
18 | class CRemoteXYDebugLog {
19 | public:
20 | HardwareSerial * serial;
21 | long speed;
22 | uint8_t inited;
23 |
24 | private:
25 | uint8_t debug_flags;
26 | uint8_t debug_hexcounter;
27 |
28 | public:
29 | CRemoteXYDebugLog (HardwareSerial * _serial, long _speed) {
30 | debug_flags=0;
31 | serial = _serial;
32 | speed = _speed;
33 | inited = 0;
34 | }
35 |
36 | public:
37 | void init () {
38 | if (!inited) {
39 | serial->begin (speed);
40 | serial->println ();
41 | write ("Debug log started");
42 | inited = 1;
43 | }
44 | }
45 |
46 |
47 | public:
48 | void writeTime () {
49 | uint32_t d = millis();
50 | long ds = d/1000;
51 | long dm = d%1000;
52 | char s[15];
53 | sprintf (s, "[%5ld.%03ld] ",ds, dm);
54 | serial->println ();
55 | serial->print (s);
56 | }
57 |
58 |
59 | public:
60 | void write (const char *s) {
61 | debug_flags = 0;
62 | writeTime ();
63 | serial->print(s);
64 | }
65 |
66 | public:
67 | void writeAdd (const char *s) {
68 | serial->print(s);
69 | }
70 |
71 |
72 | public:
73 | void writeAdd (uint16_t i) {
74 | serial->print(i);
75 | }
76 |
77 | public:
78 | void writeAdd (uint32_t i) {
79 | serial->print(i);
80 | }
81 |
82 | public:
83 | void writeAdd (int i) {
84 | serial->print(i);
85 | }
86 |
87 | public:
88 | void writeAdd (long i) {
89 | serial->print(i);
90 | }
91 |
92 | public:
93 | void writeInput (const char *s) {
94 | if ((debug_flags & 0x01)==0) {
95 | writeTime ();
96 | serial->print("<- ");
97 | }
98 | debug_flags = 0x01;
99 | serial->print(s);
100 | }
101 |
102 | public:
103 | void writeOutput (const char *s) {
104 | if ((debug_flags & 0x02)==0) {
105 | writeTime ();
106 | serial->print("-> ");
107 | }
108 | debug_flags = 0x02;
109 | serial->print(s);
110 | }
111 |
112 | public:
113 | void writeInputHex (uint8_t b) {
114 | if ((debug_flags & 0x01)==0) {
115 | writeTime ();
116 | serial->print("<-");
117 | debug_hexcounter=0;
118 | }
119 | debug_flags = 0x01;
120 | writeHex (b);
121 | }
122 |
123 | public:
124 | void writeOutputHex (uint8_t b) {
125 | if ((debug_flags & 0x02)==0) {
126 | writeTime ();
127 | serial->print("->");
128 | debug_hexcounter=0;
129 | }
130 | debug_flags = 0x02;
131 | writeHex (b);
132 | }
133 |
134 | public:
135 | void writeInputChar (char s) {
136 | if ((debug_flags & 0x01)==0) {
137 | writeTime ();
138 | serial->print("<- ");
139 | }
140 | debug_flags = 0x01;
141 | serial->print(s);
142 | }
143 |
144 | public:
145 | void writeInputNewString () {
146 | debug_flags = 0;
147 | }
148 |
149 | public:
150 | void writeHex (uint8_t b) {
151 | debug_hexcounter++;
152 | if (debug_hexcounter>16) {
153 | serial->println();
154 | serial->print(" ");
155 | debug_hexcounter=1;
156 | }
157 | serial->print(' ');
158 | serial->print(b>>4, HEX);
159 | serial->print(b&0x0f, HEX);
160 | }
161 |
162 | public:
163 | void writeAvailableMemory () {
164 | write ( "Available memory: " );
165 | writeAdd (availableMemory());
166 | }
167 |
168 |
169 |
170 | private:
171 | uint32_t availableMemory() {
172 | #if defined (ESP8266) || defined (ESP32)
173 | return ESP.getFreeHeap ();
174 | #elif defined (__AVR__)
175 | uint16_t size = RAMEND;
176 | uint8_t *buf;
177 | while ((buf = (uint8_t *)malloc(size)) == NULL) size--;
178 | free(buf);
179 | return size;
180 | #else
181 | return 0;
182 | #endif
183 | }
184 |
185 |
186 | };
187 |
188 |
189 | CRemoteXYDebugLog RemoteXYDebugLog (& REMOTEXY__DEBUGLOG_SERIAL, REMOTEXY__DEBUGLOG_SPEED);
190 |
191 |
192 | #endif //REMOTEXY__DEBUGLOG
193 |
194 | #endif //_REMOTEXY_DEBUGLOG_H_
--------------------------------------------------------------------------------
/src/RemoteXYFunc.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYFunc_h
2 | #define RemoteXYFunc_h
3 |
4 | #include
5 |
6 |
7 | char* rxy_itos (uint16_t i, char* s) {
8 | uint8_t len=0;
9 | char *p=s+5;
10 | while (i) {
11 | *p--=i%10+'0';
12 | i/=10;
13 | len++;
14 | }
15 | for (i=0; i0; i--) {
31 | b=rxy_xctoi (*s++)<<4;
32 | b|=rxy_xctoi (*s++);
33 | *m++=b;
34 | s++;
35 | }
36 | }
37 |
38 |
39 |
40 | #endif //RemoteXYFunc_h
--------------------------------------------------------------------------------
/src/RemoteXYStream.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYStream_h
2 | #define RemoteXYStream_h
3 |
4 | #include
5 | #include "RemoteXYDebugLog.h"
6 |
7 | #define UNUSED(x) (void)(x)
8 |
9 | class CRemoteXYReadByteListener {
10 | public:
11 | virtual void readByte (uint8_t byte) = 0;
12 | };
13 |
14 |
15 | class CRemoteXYStream {
16 | private:
17 | CRemoteXYReadByteListener * readByteListener;
18 |
19 |
20 | public:
21 | CRemoteXYStream () {
22 | readByteListener = NULL;
23 | #if defined(REMOTEXY__DEBUGLOG)
24 | RemoteXYDebugLog.init ();
25 | #endif
26 | }
27 |
28 | public:
29 | void setReadByteListener (CRemoteXYReadByteListener * listener) {
30 | readByteListener = listener;
31 | }
32 |
33 | public:
34 | void notifyReadByteListener (uint8_t byte) {
35 | if (readByteListener) readByteListener->readByte (byte);
36 | }
37 |
38 | public:
39 | virtual void handler () {};
40 | virtual void startWrite (uint16_t size) {UNUSED (size);};
41 | virtual void write (uint8_t byte) {UNUSED (byte);};
42 | };
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | #endif //RemoteXYStream_h
--------------------------------------------------------------------------------
/src/RemoteXYStream_BLEDevice.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYStream_BLEDevice_h
2 | #define RemoteXYStream_BLEDevice_h
3 |
4 | #if defined(MAIN_BLEDevice_H_)
5 |
6 | #include "RemoteXYComm.h"
7 | #include
8 |
9 |
10 | #define REMOTEXYCOMM_BLEDEVICE__SEND_BUFFER_SIZE 20
11 | #define REMOTEXYCOMM_BLEDEVICE__RECEIVE_BUFFER_SIZE 1024
12 | #define REMOTEXYCOMM_BLEDEVICE__SERVICE_UUID "0000FFE0-0000-1000-8000-00805F9B34FB" // UART service UUID
13 | #define REMOTEXYCOMM_BLEDEVICE__CHARACTERISTIC_UUID_RXTX "0000FFE1-0000-1000-8000-00805F9B34FB"
14 |
15 |
16 | class CRemoteXYStream_BLEDevice : public CRemoteXYStream, BLEServerCallbacks, BLECharacteristicCallbacks {
17 |
18 | protected:
19 | const char * bleDeviceName; // need to delete
20 |
21 | BLEServer *pServer;
22 | BLECharacteristic * pRxTxCharacteristic;
23 |
24 | uint8_t sendBuffer[REMOTEXYCOMM_BLEDEVICE__SEND_BUFFER_SIZE];
25 | uint16_t sendBufferCount;
26 | uint16_t sendBytesAvailable;
27 |
28 | uint8_t receiveBuffer[REMOTEXYCOMM_BLEDEVICE__RECEIVE_BUFFER_SIZE];
29 | uint16_t receiveBufferStart;
30 | uint16_t receiveBufferPos;
31 | uint16_t receiveBufferCount;
32 |
33 | volatile uint8_t receiveBufferLook;
34 |
35 | public:
36 | CRemoteXYStream_BLEDevice (const char * _bleDeviceName) : CRemoteXYStream () {
37 | bleDeviceName = _bleDeviceName;
38 |
39 | receiveBufferLook = 0;
40 | receiveBufferCount = 0;
41 | receiveBufferStart = 0;
42 | receiveBufferPos = 0;
43 | receiveBufferCount = 0;
44 |
45 | #if defined(REMOTEXY__DEBUGLOG)
46 | RemoteXYDebugLog.write("Init ESP32 BLE on chip");
47 | #endif
48 | // Create the BLE Device
49 | BLEDevice::init(_bleDeviceName);
50 |
51 | // Create the BLE Server
52 | pServer = BLEDevice::createServer();
53 | pServer->setCallbacks(this);
54 |
55 | // Create the BLE Service
56 | BLEService *pService = pServer->createService(REMOTEXYCOMM_BLEDEVICE__SERVICE_UUID);
57 |
58 | // Create a BLE Characteristic
59 | pRxTxCharacteristic = pService->createCharacteristic(
60 | REMOTEXYCOMM_BLEDEVICE__CHARACTERISTIC_UUID_RXTX,
61 | BLECharacteristic::PROPERTY_READ |
62 | BLECharacteristic::PROPERTY_NOTIFY |
63 | BLECharacteristic::PROPERTY_WRITE_NR
64 | );
65 |
66 | BLE2902 *ble2902 = new BLE2902();
67 | ble2902->setNotifications(true);
68 | pRxTxCharacteristic->addDescriptor(ble2902);
69 | pRxTxCharacteristic->setCallbacks(this);
70 |
71 | // Start the service
72 | pService->start();
73 |
74 | // Start advertising
75 | pServer->getAdvertising()->addServiceUUID(pService->getUUID());
76 | pServer->getAdvertising()->start();
77 |
78 | #if defined(REMOTEXY__DEBUGLOG)
79 | RemoteXYDebugLog.write("BLE started");
80 | #endif
81 |
82 | }
83 |
84 | void onConnect(BLEServer* pServer) {
85 | #if defined(REMOTEXY__DEBUGLOG)
86 | RemoteXYDebugLog.write("BLE client connected");
87 | #endif
88 | receiveBufferStart = 0;
89 | receiveBufferPos = 0;
90 | receiveBufferCount = 0;
91 | };
92 |
93 | void onDisconnect(BLEServer* pServer) {
94 | #if defined(REMOTEXY__DEBUGLOG)
95 | RemoteXYDebugLog.write("BLE client disconnected");
96 | #endif
97 | receiveBufferCount = 0;
98 | pServer->getAdvertising ()->start ();
99 | }
100 |
101 | void onWrite (BLECharacteristic *pCharacteristic) {
102 | std::string rxValue = pCharacteristic->getValue();
103 |
104 | if (rxValue.length() > 0) {
105 | while (receiveBufferLook!=0) { delay(1); }
106 | receiveBufferLook=1;
107 | for (uint16_t i = 0; i < rxValue.length(); i++) {
108 | uint8_t b = (uint8_t)rxValue[i];
109 | receiveBuffer[receiveBufferPos++] = b;
110 | if (receiveBufferPos >= REMOTEXYCOMM_BLEDEVICE__RECEIVE_BUFFER_SIZE) receiveBufferPos=0;
111 | if (receiveBufferCount < REMOTEXYCOMM_BLEDEVICE__RECEIVE_BUFFER_SIZE) receiveBufferCount++;
112 | else {
113 | receiveBufferStart++;
114 | if (receiveBufferStart >= REMOTEXYCOMM_BLEDEVICE__RECEIVE_BUFFER_SIZE) receiveBufferStart=0;
115 | }
116 | }
117 | receiveBufferLook=0;
118 | }
119 | }
120 |
121 |
122 | void startWrite (uint16_t len) override {
123 | sendBytesAvailable = len;
124 | sendBufferCount = 0;
125 | }
126 |
127 |
128 | void write (uint8_t b) override {
129 | sendBuffer[sendBufferCount++] = b;
130 | sendBytesAvailable--;
131 | if ((sendBufferCount == REMOTEXYCOMM_BLEDEVICE__SEND_BUFFER_SIZE) || (sendBytesAvailable == 0)) {
132 | pRxTxCharacteristic->setValue((uint8_t *)sendBuffer, sendBufferCount);
133 | pRxTxCharacteristic->notify();
134 | sendBufferCount = 0;
135 | }
136 | }
137 |
138 | void handler () override {
139 | if (receiveBufferCount>0) {
140 | while (receiveBufferLook!=0) { delay(1); }
141 | receiveBufferLook=1;
142 | while (receiveBufferCount) {
143 | notifyReadByteListener (receiveBuffer[receiveBufferStart++]);
144 | if (receiveBufferStart >= REMOTEXYCOMM_BLEDEVICE__RECEIVE_BUFFER_SIZE) receiveBufferStart=0;
145 | receiveBufferCount--;
146 | }
147 | receiveBufferLook=0;
148 | }
149 | }
150 |
151 |
152 |
153 | };
154 |
155 | #endif // MAIN_BLEDevice_H_
156 | #endif // RemoteXYStream_BLEDevice_h
--------------------------------------------------------------------------------
/src/RemoteXYStream_BLEPeripheral.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYStream_BLEPeripheral_h
2 | #define RemoteXYStream_BLEPeripheral_h
3 |
4 | #if defined(_BLE_PERIPHERAL_H_)
5 |
6 | #include "RemoteXYStream.h"
7 |
8 | #define REMOTEXYCOMM_BLEPERIPHERAL__SEND_BUFFER_SIZE BLE_ATTRIBUTE_MAX_VALUE_LENGTH
9 | #define REMOTEXYCOMM_BLEPERIPHERAL__RECEIVE_BUFFER_SIZE 1024
10 | #define REMOTEXYCOMM_BLEPERIPHERAL__SERVICE_UUID "0000FFE0-0000-1000-8000-00805F9B34FB" // UART service UUID
11 | #define REMOTEXYCOMM_BLEPERIPHERAL__CHARACTERISTIC_UUID "0000FFE1-0000-1000-8000-00805F9B34FB"
12 | //#define REMOTEXYCOMM_BLEPERIPHERAL__DESCRIPTOR_UUID "2902"
13 |
14 | #define REMOTEXYCOMM_BLEPERIPHERAL__CANNOTIFY_TIMEOUT 1000
15 |
16 | class CRemoteXYStream_BLEPeripheral : public CRemoteXYStream, public BLEPeripheral {
17 |
18 | private:
19 | BLEService *pService;
20 | BLECharacteristic *pCharacteristic;
21 | BLEDescriptor *pDescriptor;
22 |
23 | uint8_t sendBuffer[REMOTEXYCOMM_BLEPERIPHERAL__SEND_BUFFER_SIZE];
24 | uint16_t sendBufferCount;
25 | uint16_t sendBytesAvailable;
26 |
27 | uint8_t receiveBuffer[REMOTEXYCOMM_BLEPERIPHERAL__RECEIVE_BUFFER_SIZE];
28 | uint16_t receiveBufferStart;
29 | uint16_t receiveBufferPos;
30 | uint16_t receiveBufferCount;
31 |
32 |
33 | public:
34 | CRemoteXYStream_BLEPeripheral (const char * _bleDeviceName) : CRemoteXYStream (), BLEPeripheral () {
35 | #if defined(REMOTEXY__DEBUGLOG)
36 | RemoteXYDebugLog.write("Init NRF BLE on chip");
37 | #endif
38 |
39 | receiveBufferCount = 0;
40 | receiveBufferStart = 0;
41 | receiveBufferPos = 0;
42 | receiveBufferCount = 0;
43 |
44 | pService = new BLEService (REMOTEXYCOMM_BLEPERIPHERAL__SERVICE_UUID);
45 | pCharacteristic = new BLECharacteristic( REMOTEXYCOMM_BLEPERIPHERAL__CHARACTERISTIC_UUID, BLERead | BLEWriteWithoutResponse | BLENotify, BLE_ATTRIBUTE_MAX_VALUE_LENGTH);
46 | //pDescriptor = new BLEDescriptor(REMOTEXYCOMM_BLEPERIPHERAL__DESCRIPTOR_UUID);
47 |
48 | setLocalName(_bleDeviceName);
49 | setDeviceName(_bleDeviceName);
50 | setAdvertisedServiceUuid (pService->uuid());
51 | setAppearance(0x0080);
52 |
53 | addAttribute (*pService);
54 | addAttribute (*pCharacteristic);
55 | //addAttribute (*pDescriptor);
56 |
57 | pCharacteristic->setValue(0);
58 | begin();
59 |
60 | #if defined(REMOTEXY__DEBUGLOG)
61 | RemoteXYDebugLog.write("BLE started");
62 | #endif
63 |
64 | }
65 |
66 |
67 | void BLEDeviceConnected(BLEDevice& device, const unsigned char* address) override {
68 | #if defined(REMOTEXY__DEBUGLOG)
69 | RemoteXYDebugLog.write("BLE client connected");
70 | #endif
71 | receiveBufferStart = 0;
72 | receiveBufferPos = 0;
73 | receiveBufferCount = 0;
74 | }
75 |
76 | void BLEDeviceDisconnected(BLEDevice& device) {
77 | #if defined(REMOTEXY__DEBUGLOG)
78 | RemoteXYDebugLog.write("BLE client disconnected");
79 | #endif
80 | receiveBufferCount = 0;
81 | }
82 |
83 | void BLEDeviceCharacteristicValueChanged (BLEDevice& device, BLECharacteristic& characteristic, const unsigned char* data, unsigned char size) override {
84 |
85 | for (uint16_t i = 0; i < size; i++) {
86 | receiveBuffer[receiveBufferPos++] = data[i];
87 | if (receiveBufferPos >= REMOTEXYCOMM_BLEPERIPHERAL__RECEIVE_BUFFER_SIZE) receiveBufferPos=0;
88 | if (receiveBufferCount < REMOTEXYCOMM_BLEPERIPHERAL__RECEIVE_BUFFER_SIZE) receiveBufferCount++;
89 | else {
90 | receiveBufferStart++;
91 | if (receiveBufferStart >= REMOTEXYCOMM_BLEPERIPHERAL__RECEIVE_BUFFER_SIZE) receiveBufferStart=0;
92 | }
93 | }
94 |
95 | }
96 |
97 |
98 | void startWrite (uint16_t len) override {
99 | sendBytesAvailable = len;
100 | sendBufferCount = 0;
101 | }
102 |
103 | void write (uint8_t b) override {
104 | if (pCharacteristic->subscribed() == false) {
105 | #if defined(REMOTEXY__DEBUGLOG)
106 | RemoteXYDebugLog.write("BLE: tx characteristic not subscribed");
107 | #endif
108 | return;
109 | }
110 | sendBuffer[sendBufferCount++] = b;
111 | sendBytesAvailable--;
112 | if ((sendBufferCount == REMOTEXYCOMM_BLEPERIPHERAL__SEND_BUFFER_SIZE) || (sendBytesAvailable == 0)) {
113 | uint32_t t = millis ();
114 | while (pCharacteristic->canNotify () == 0) {
115 | if (millis () - t > REMOTEXYCOMM_BLEPERIPHERAL__CANNOTIFY_TIMEOUT) break;
116 | poll();
117 | }
118 | pCharacteristic->setValue(sendBuffer, sendBufferCount);
119 | poll();
120 | sendBufferCount = 0;
121 |
122 | }
123 | }
124 |
125 | void handler () override {
126 | uint8_t b;
127 | BLEPeripheral::poll();
128 | while (receiveBufferCount > 0) {
129 | b = receiveBuffer[receiveBufferStart++];
130 | if (receiveBufferStart >= REMOTEXYCOMM_BLEPERIPHERAL__RECEIVE_BUFFER_SIZE) receiveBufferStart=0;
131 | receiveBufferCount--;
132 | notifyReadByteListener (b);
133 | }
134 | }
135 | };
136 |
137 |
138 |
139 |
140 |
141 | #endif // _BLE_PERIPHERAL_H_
142 |
143 | #endif //RemoteXYStream_BLEPeripheral_h
--------------------------------------------------------------------------------
/src/RemoteXYStream_BluetoothSerial.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYStream_BluetoothSerial_h
2 | #define RemoteXYStream_BluetoothSerial_h
3 |
4 | #if defined (BluetoothSerial_h) || defined (_BLUETOOTH_SERIAL_H_)
5 |
6 | #include "RemoteXYComm.h"
7 |
8 |
9 | class CRemoteXYStream_BluetoothSerial : public CRemoteXYStream {
10 |
11 | private:
12 | BluetoothSerial * serial;
13 |
14 | public:
15 | CRemoteXYStream_BluetoothSerial (const char * _bleDeviceName) : CRemoteXYStream () {
16 | serial = new BluetoothSerial ();
17 | serial->begin (_bleDeviceName);
18 |
19 | #if defined(REMOTEXY__DEBUGLOG)
20 | RemoteXYDebugLog.write("Init bluetooth serial");
21 | #endif
22 | }
23 |
24 |
25 | void handler () override {
26 | while (serial->available ()) notifyReadByteListener (serial->read ());
27 | }
28 |
29 |
30 | void write (uint8_t byte) override {
31 | serial->write (byte);
32 | }
33 |
34 |
35 | };
36 |
37 | #endif // BluetoothSerial_h _BLUETOOTH_SERIAL_H_
38 | #endif //RemoteXYStream_BluetoothSerial_h
--------------------------------------------------------------------------------
/src/RemoteXYStream_CDCSerial.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYStream_CDCSerial_h
2 | #define RemoteXYStream_CDCSerial_h
3 |
4 | #if defined(USBCON)
5 |
6 | #include "RemoteXYStream.h"
7 |
8 |
9 | class CRemoteXYStream_CDCSerial : public CRemoteXYStream {
10 |
11 | private:
12 | Serial_ * serial;
13 |
14 | public:
15 | CRemoteXYStream_CDCSerial (Serial_ * _serial, long _serialSpeed) : CRemoteXYStream () {
16 | serial = _serial;
17 | serial->begin (_serialSpeed);
18 | #if defined(REMOTEXY__DEBUGLOG)
19 | RemoteXYDebugLog.write("Init CDC serial ");
20 | RemoteXYDebugLog.writeAdd(_serialSpeed);
21 | RemoteXYDebugLog.writeAdd(" baud");
22 | #endif
23 | }
24 |
25 | void handler () override {
26 | while (serial->available ()) notifyReadByteListener (serial->read ());
27 | }
28 |
29 | void write (uint8_t byte) override {
30 | serial->write (byte);
31 | }
32 |
33 | };
34 |
35 |
36 | #endif //USBCON
37 |
38 | #endif //RemoteXYStream_CDCSerial_h
--------------------------------------------------------------------------------
/src/RemoteXYStream_HardSerial.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYStream_HardSerial_h
2 | #define RemoteXYStream_HardSerial_h
3 |
4 | #include "RemoteXYStream.h"
5 |
6 |
7 | class CRemoteXYStream_HardSerial : public CRemoteXYStream {
8 |
9 | private:
10 | HardwareSerial * serial;
11 |
12 | public:
13 | CRemoteXYStream_HardSerial (HardwareSerial * _serial, long _serialSpeed) : CRemoteXYStream () {
14 | serial = _serial;
15 | serial->begin (_serialSpeed);
16 | #if defined(REMOTEXY__DEBUGLOG)
17 | RemoteXYDebugLog.write("Init hardware serial ");
18 | RemoteXYDebugLog.writeAdd(_serialSpeed);
19 | RemoteXYDebugLog.writeAdd(" baud");
20 | #endif
21 | }
22 |
23 | void handler () override {
24 | while (serial->available ()) notifyReadByteListener (serial->read ());
25 | }
26 |
27 | void write (uint8_t byte) override {
28 | serial->write (byte);
29 | }
30 |
31 | };
32 |
33 |
34 |
35 |
36 | #endif //RemoteXYStream_HardSerial_h
--------------------------------------------------------------------------------
/src/RemoteXYStream_SoftSerial.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYStream_SoftSerial_h
2 | #define RemoteXYStream_SoftSerial_h
3 |
4 |
5 | // if not defined SoftwareSerial.h
6 | #if defined(REMOTEXY_MODE__SOFTSERIAL) || defined(REMOTEXY_MODE__ESP8266_SOFTSERIAL_POINT) || defined(REMOTEXY_MODE__SOFTSERIAL_ESP8266) || defined(REMOTEXY_MODE__SOFTSERIAL_ESP8266_CLOUD)
7 | #if !defined (SoftwareSerial_h) && !defined(SoftSerial_h)
8 | #include "SoftwareSerial.h"
9 | #endif
10 | #endif
11 |
12 | #if defined(SoftwareSerial_h) || defined(SoftSerial_h)
13 |
14 | #include "RemoteXYComm.h"
15 |
16 |
17 | class CRemoteXYStream_SoftSerial : public CRemoteXYStream {
18 |
19 | #if defined(SoftwareSerial_h)
20 |
21 | private:
22 | SoftwareSerial * serial;
23 |
24 | public:
25 | CRemoteXYStream_SoftSerial (uint8_t _serialRx, uint8_t _serialTx, long _serialSpeed) : CRemoteXYStream () {
26 | serial = new SoftwareSerial (_serialRx, _serialTx);
27 | serial->begin (_serialSpeed);
28 | #if defined(REMOTEXY__DEBUGLOG)
29 | RemoteXYDebugLog.write("Init software serial ");
30 | RemoteXYDebugLog.writeAdd(_serialSpeed);
31 | RemoteXYDebugLog.writeAdd(" baud");
32 | RemoteXYDebugLog.write("pin RX=");
33 | RemoteXYDebugLog.writeAdd(_serialRx);
34 | RemoteXYDebugLog.writeAdd("; pin TX=");
35 | RemoteXYDebugLog.writeAdd(_serialTx);
36 | #endif
37 | }
38 |
39 | #elif defined(SoftSerial_h)
40 |
41 | private:
42 | SoftSerial * serial;
43 |
44 | public:
45 | CRemoteXYStream_SoftSerial (uint8_t _serialRx, uint8_t _serialTx, long _serialSpeed) : CRemoteXYStream () {
46 | serial = new SoftSerial (_serialRx, _serialTx);
47 | serial->begin (_serialSpeed);
48 | #if defined(REMOTEXY__DEBUGLOG)
49 | RemoteXYDebugLog.write("Init soft serial ");
50 | RemoteXYDebugLog.writeAdd(_serialSpeed);
51 | RemoteXYDebugLog.writeAdd(" baud");
52 | RemoteXYDebugLog.write("pin RX=");
53 | RemoteXYDebugLog.writeAdd(_serialRx);
54 | RemoteXYDebugLog.writeAdd("; pin TX=");
55 | RemoteXYDebugLog.writeAdd(_serialTx);
56 | #endif
57 | }
58 |
59 |
60 | #endif
61 |
62 | void handler () override {
63 | while (serial->available ()) notifyReadByteListener (serial->read ());
64 | }
65 |
66 | void write (uint8_t byte) override {
67 | serial->write (byte);
68 | }
69 |
70 |
71 | };
72 |
73 |
74 | #endif // SoftwareSerial_h SoftSerial_h
75 |
76 | #endif //RemoteXYStream_SoftSerial_h
--------------------------------------------------------------------------------
/src/RemoteXYThread.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYThread_h
2 | #define RemoteXYThread_h
3 |
4 |
5 | #include "RemoteXYApiData.h"
6 | #include "RemoteXYComm.h"
7 | #include "RemoteXYConnection.h"
8 | #include "RemoteXYWire.h"
9 |
10 |
11 | #define REMOTEXY_INIT_CRC 0xffff
12 | #define REMOTEXY_PACKAGE_START_BYTE 0x55
13 | #define REMOTEXY_THREAD_TIMEOUT 8000
14 |
15 |
16 | class CRemoteXYThread : public CRemoteXYReceivePackageListener {
17 |
18 | public:
19 | CRemoteXYThread * next;
20 |
21 | private:
22 | CRemoteXYData* data;
23 | CRemoteXYConnection* conn;
24 | CRemoteXYWire * wire;
25 |
26 | uint8_t *inputVar;
27 |
28 | uint32_t timeOut;
29 | uint8_t stopByTimeOut;
30 |
31 | uint8_t inputVarNeedSend;
32 |
33 |
34 | public:
35 | uint8_t connect_flag;
36 |
37 | public:
38 | CRemoteXYThread (CRemoteXYData * _data) {
39 |
40 | data = _data;
41 | wire = NULL;
42 |
43 | inputVar = (uint8_t*)malloc (data->inputLength);
44 | copyInputVars ();
45 | }
46 |
47 |
48 |
49 | public:
50 | void begin (CRemoteXYConnection * _conn, CRemoteXYWire * _wire, uint8_t _stopByTimeOut) {
51 | conn = _conn;
52 | wire = _wire;
53 | wire->setReceivePackageListener (this);
54 | stopByTimeOut = _stopByTimeOut;
55 | timeOut = millis ();
56 | connect_flag = 0;
57 |
58 | #if defined(REMOTEXY__DEBUGLOG)
59 | RemoteXYDebugLog.write("Client started");
60 | //RemoteXYDebugLog.writeAvailableMemory ();
61 | #endif
62 | }
63 |
64 |
65 | public:
66 | void stop () {
67 | if (wire) {
68 | conn->stopThreadListener (wire);
69 | wire = NULL;
70 | connect_flag = 0;
71 | #if defined(REMOTEXY__DEBUGLOG)
72 | RemoteXYDebugLog.write("Client stoped");
73 | #endif
74 | }
75 | }
76 |
77 | public:
78 | uint8_t running () {
79 | if (wire) return 1;
80 | return 0;
81 | }
82 |
83 |
84 | public:
85 | void receivePackage (CRemoteXYPackage * package) override {
86 | uint16_t i, length;
87 | uint8_t *p, *kp, *ip;
88 |
89 | if (wire == NULL) return;
90 | if ((package->command != 0x00) && (!connect_flag)) return;
91 | switch (package->command) {
92 | case 0x00:
93 | uint8_t available;
94 | if (package->length==0) {
95 | if (*data->accessPassword==0) available=1;
96 | else available=0;
97 | }
98 | else {
99 | uint8_t ch;
100 | available = 1;
101 | p = package->buffer;
102 | kp = data->accessPassword;
103 | while (true) {
104 | ch=*kp++;
105 | if (ch!=*p++) available=0;
106 | if (!ch) break;
107 | }
108 | }
109 | if (available!=0) {
110 | wire->sendPackage (0x00, data->conf, data->confLength, 1);
111 | connect_flag = 1;
112 | }
113 | else {
114 | uint8_t buf[4];
115 | p = buf;
116 | kp = data->conf;
117 | i=data->confVersion>=5?3:2;
118 | length = i+1;
119 | while (i--) *p++ = data->getConfByte(kp++);
120 | *p++ = 0xf0;
121 | wire->sendPackage (0x00, buf, length, 0);
122 | }
123 | break;
124 | case 0x40:
125 | copyInputVars ();
126 | wire->sendPackage (0x40, data->var, data->inputLength + data->outputLength, 0);
127 | break;
128 | case 0x80:
129 | checkInputVars ();
130 | if ((package->length == data->inputLength) && (inputVarNeedSend==0)) {
131 | p=package->buffer;
132 | kp=data->var;
133 | ip=inputVar;
134 | i= data->inputLength;
135 | while (i--) *ip++=*kp++=*p++;
136 | }
137 | wire->sendPackage (0x80, 0, 0, 0);
138 | break;
139 | case 0xC0:
140 | checkInputVars ();
141 | uint8_t c;
142 | if (inputVarNeedSend==0) c = 0xC0;
143 | else c = 0xC1;
144 | wire->sendPackage (c, data->var + data->inputLength, data->outputLength, 0);
145 | break;
146 | }
147 | timeOut = millis ();
148 | }
149 |
150 | private:
151 | void copyInputVars () {
152 | inputVarNeedSend = 0;
153 | uint8_t * pc = data->var;
154 | uint8_t * p = inputVar;
155 | uint16_t ilen = data->inputLength;
156 | while (ilen--) *p++ = *pc++;
157 | }
158 |
159 | private:
160 | void checkInputVars () {
161 | if (inputVarNeedSend) return;
162 | uint8_t * pc = data->var;
163 | uint8_t * p = inputVar;
164 | uint16_t ilen = data->inputLength;
165 | while (ilen--) {
166 | if (*p++ != *pc++) {
167 | inputVarNeedSend = 1;
168 | break;
169 | }
170 | }
171 | }
172 |
173 |
174 |
175 | public:
176 | void handler () {
177 | if (wire) {
178 | conn->handleWire (wire);
179 | if (wire->running ()) {
180 | if (millis () - timeOut > REMOTEXY_THREAD_TIMEOUT) {
181 | timeOut = millis ();
182 | connect_flag = 0;
183 | if (stopByTimeOut) stop ();
184 | }
185 | }
186 | else stop ();
187 | }
188 | }
189 |
190 | public:
191 | static void startThread (CRemoteXYData * data, CRemoteXYConnection * conn, CRemoteXYWire * wire, uint8_t stopByTimeOut) {
192 | CRemoteXYThread * pt = data->threads;
193 | while (pt) {
194 | if (!pt->running ()) {
195 | pt->begin (conn, wire, stopByTimeOut);
196 | return;
197 | }
198 | pt = pt->next;
199 | }
200 | pt = new CRemoteXYThread (data);
201 | pt->next = data->threads;
202 | data->threads = pt;
203 | pt->begin (conn, wire, stopByTimeOut);
204 | }
205 |
206 | public:
207 | static uint8_t runningCount (CRemoteXYData * data) {
208 | uint8_t c = 0;
209 | CRemoteXYThread * pt = data->threads;
210 | while (pt) {
211 | if (pt->running ()) c++;
212 | pt = pt->next;
213 | }
214 | return c;
215 | }
216 |
217 | };
218 |
219 |
220 | #endif //RemoteXYThread_h
--------------------------------------------------------------------------------
/src/RemoteXYWire.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYWire_h
2 | #define RemoteXYWire_h
3 |
4 | #include "RemoteXYComm.h"
5 |
6 | #define REMOTEXY_INIT_CRC 0xffff
7 | #define REMOTEXY_PACKAGE_START_BYTE 0x55
8 | #define REMOTEXY_PACKAGE_MIN_LENGTH 6
9 |
10 |
11 | struct CRemoteXYPackage {
12 | uint8_t command;
13 | uint8_t * buffer;
14 | uint16_t length;
15 | };
16 |
17 | class CRemoteXYReceivePackageListener {
18 | public:
19 | virtual void receivePackage (CRemoteXYPackage * package) = 0;
20 | };
21 |
22 | class CRemoteXYWire {
23 |
24 | private:
25 | CRemoteXYReceivePackageListener * receivePackageListener;
26 |
27 | public:
28 | CRemoteXYWire () {
29 | receivePackageListener = NULL;
30 | }
31 |
32 | public:
33 | void setReceivePackageListener (CRemoteXYReceivePackageListener * listener) {
34 | receivePackageListener = listener;
35 | }
36 |
37 | public:
38 | void notifyReceivePackageListener (CRemoteXYPackage * package) {
39 | if (receivePackageListener) receivePackageListener->receivePackage (package);
40 | }
41 |
42 |
43 | public:
44 | virtual void handler () {};
45 | virtual uint8_t running ();
46 | virtual void stop ();
47 | virtual void sendPackage (uint8_t command, uint8_t *buf, uint16_t length, uint8_t fromPgm);
48 |
49 | };
50 |
51 |
52 | #endif // RemoteXYWire_h
--------------------------------------------------------------------------------
/src/RemoteXYWireCloud.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYWireCloud_h
2 | #define RemoteXYWireCloud_h
3 |
4 | #include "RemoteXYWire.h"
5 |
6 |
7 | #define REMOTEXYWIRECLOUD_FREE_ID 0xff
8 |
9 |
10 | class CRemoteXYSendPackageListener {
11 | public:
12 | virtual void sendPackage (uint8_t command, uint8_t *buf, uint16_t length, uint8_t fromPgm) = 0;
13 | };
14 |
15 | class CRemoteXYWireCloud: public CRemoteXYWire {
16 |
17 | public:
18 | CRemoteXYWireCloud * next;
19 | uint8_t id; // 0..7
20 | uint8_t newConnection;
21 |
22 | private:
23 | CRemoteXYSendPackageListener * sendPackageListener;
24 |
25 | public:
26 | CRemoteXYWireCloud (CRemoteXYSendPackageListener * _sendPackageListener) : CRemoteXYWire () {
27 | sendPackageListener = _sendPackageListener;
28 | id = REMOTEXYWIRECLOUD_FREE_ID;
29 | newConnection = 0;
30 | }
31 |
32 | public:
33 | void init (uint8_t _id) {
34 | id = _id;
35 | newConnection = 1;
36 | }
37 |
38 | /*
39 | public:
40 | void begin () {
41 | newConnection = 0;
42 | }
43 | */
44 |
45 | public:
46 | void stop () override {
47 | setReceivePackageListener (NULL);
48 | id = REMOTEXYWIRECLOUD_FREE_ID;
49 | newConnection = 0;
50 | }
51 |
52 | public:
53 | uint8_t running () override {
54 | if (id == REMOTEXYWIRECLOUD_FREE_ID) return 0;
55 | return 1;
56 | }
57 |
58 | public:
59 | uint8_t isNewConnection () {
60 | return newConnection;
61 | }
62 |
63 |
64 | public:
65 | void sendPackage (uint8_t command, uint8_t *buf, uint16_t length, uint8_t fromPgm) override {
66 | sendPackageListener->sendPackage (command | (id<<1), buf, length, fromPgm);
67 | }
68 |
69 |
70 | public:
71 | void receivePackage (CRemoteXYPackage * package) {
72 | notifyReceivePackageListener (package);
73 | }
74 |
75 | };
76 |
77 | #endif //RemoteXYWireCloud_h
--------------------------------------------------------------------------------
/src/RemoteXYWireStream.h:
--------------------------------------------------------------------------------
1 | #ifndef RemoteXYWireStream_h
2 | #define RemoteXYWireStream_h
3 |
4 |
5 | #include "RemoteXYWire.h"
6 | #include "RemoteXYApiData.h"
7 |
8 |
9 | class CRemoteXYWireStream : public CRemoteXYWire, public CRemoteXYReadByteListener {
10 |
11 | public:
12 | CRemoteXYWireStream * next;
13 | CRemoteXYStream * stream;
14 |
15 | private:
16 | uint16_t sendCRC;
17 |
18 | uint8_t *receiveBuffer;
19 | uint16_t receiveBufferSize;
20 | uint16_t receiveIndex;
21 | uint8_t receiveModified;
22 | volatile uint8_t receiveLock; // =1 only add to receive buffer
23 |
24 |
25 | public:
26 | CRemoteXYWireStream (CRemoteXYData * data) : CRemoteXYWire () {
27 | stream = NULL;
28 | receiveBufferSize = data->receiveBufferSize;
29 | receiveBuffer = (uint8_t*)malloc (receiveBufferSize);
30 | }
31 |
32 | public:
33 | CRemoteXYWireStream (CRemoteXYData * data, uint8_t multiple) : CRemoteXYWire () {
34 | stream = NULL;
35 | receiveBufferSize = data->receiveBufferSize * multiple;
36 | receiveBuffer = (uint8_t*)malloc (receiveBufferSize);
37 | }
38 |
39 | public:
40 | void begin (CRemoteXYStream * _stream) {
41 | stream = _stream;
42 | stream->setReadByteListener (this);
43 | receiveIndex = 0;
44 | receiveModified = 0;
45 | receiveLock = 0;
46 | }
47 |
48 | public:
49 | void stop () override {
50 | setReceivePackageListener (NULL);
51 | stream = NULL;
52 | }
53 |
54 | public:
55 | uint8_t running () override {
56 | if (stream) return 1;
57 | else return 0;
58 | }
59 |
60 | CRemoteXYClient * getClient () {
61 | return (CRemoteXYClient*)stream;
62 | }
63 |
64 |
65 |
66 | public:
67 | void handler () override {
68 | if (stream) {
69 | stream->handler ();
70 | receivePackage ();
71 | }
72 | }
73 |
74 |
75 | private:
76 | void updateCRC (uint16_t *crc, uint8_t b) {
77 | *crc ^= b;
78 | for (uint8_t i=0; i<8; ++i) {
79 | if ((*crc) & 1) *crc = ((*crc) >> 1) ^ 0xA001;
80 | else *crc >>= 1;
81 | }
82 | }
83 |
84 |
85 | private:
86 | inline void sendByteUpdateCRC (uint8_t b) {
87 | #if defined(REMOTEXY__DEBUGLOG)
88 | RemoteXYDebugLog.writeOutputHex (b);
89 | #endif
90 | stream->write (b);
91 | updateCRC (&sendCRC, b);
92 | }
93 |
94 |
95 | public:
96 | void sendPackage (uint8_t command, uint8_t *buf, uint16_t length, uint8_t fromPgm) {
97 | uint16_t packageLength;
98 | if (stream) {
99 | sendCRC = REMOTEXY_INIT_CRC;
100 | packageLength = length+6;
101 | stream->startWrite (packageLength);
102 |
103 | sendByteUpdateCRC (REMOTEXY_PACKAGE_START_BYTE);
104 | sendByteUpdateCRC (packageLength);
105 | sendByteUpdateCRC (packageLength>>8);
106 | sendByteUpdateCRC (command);
107 | uint8_t b;
108 | while (length--) {
109 | if (fromPgm) b=pgm_read_byte_near (buf++);
110 | else b=*buf++;
111 | sendByteUpdateCRC (b);
112 | }
113 | #if defined(REMOTEXY__DEBUGLOG)
114 | RemoteXYDebugLog.writeOutputHex (sendCRC);
115 | RemoteXYDebugLog.writeOutputHex (sendCRC>>8);
116 | #endif
117 | stream->write (sendCRC);
118 | stream->write (sendCRC>>8);
119 | }
120 | }
121 |
122 | public:
123 | void readByte (uint8_t byte) override {
124 | uint16_t pi, i;
125 |
126 | #if defined(REMOTEXY__DEBUGLOG)
127 | RemoteXYDebugLog.writeInputHex (byte);
128 | #endif
129 | if ((receiveIndex==0) && (byte!=REMOTEXY_PACKAGE_START_BYTE)) return;
130 | if (receiveIndex >= receiveBufferSize) {
131 | if (receiveLock) return;
132 | pi = 1;
133 | while (pi < receiveBufferSize) {
134 | if (receiveBuffer[pi] == REMOTEXY_PACKAGE_START_BYTE) break;
135 | pi++;
136 | }
137 | receiveIndex = receiveBufferSize - pi;
138 | i=0;
139 | while (pi < receiveBufferSize) receiveBuffer[i++] = receiveBuffer[pi++];
140 | }
141 | receiveBuffer[receiveIndex++]=byte;
142 | receiveModified = 1;
143 | }
144 |
145 | private:
146 | void receivePackage () {
147 | if (receiveModified) {
148 | receiveModified = 0;
149 |
150 | uint16_t crc;
151 | uint16_t si, i;
152 | uint16_t packageLength;
153 | si = 0;
154 | while (si + REMOTEXY_PACKAGE_MIN_LENGTH <= receiveIndex) {
155 | if (receiveBuffer[si] == REMOTEXY_PACKAGE_START_BYTE) {
156 | packageLength = receiveBuffer[si+1]|(receiveBuffer[si+2]<<8);
157 | if ((packageLength <= receiveIndex - si) && (packageLength >=6)) {
158 | crc=REMOTEXY_INIT_CRC;
159 | for (i = si; i < si + packageLength; i++) updateCRC (&crc, receiveBuffer[i]);
160 | if (crc == 0) {
161 | CRemoteXYPackage package;
162 | package.command = receiveBuffer[si+3];
163 | package.buffer = receiveBuffer+si+4;
164 | package.length = packageLength-6;
165 |
166 | receiveLock = 1;
167 | notifyReceivePackageListener (&package);
168 | si += packageLength;
169 | i = 0;
170 | while (si < receiveIndex) receiveBuffer[i++] = receiveBuffer[si++];
171 | receiveIndex = i;
172 | receiveLock = 0;
173 | si = 0;
174 | continue;
175 | }
176 | }
177 | }
178 | si++;
179 | }
180 | }
181 | }
182 |
183 | };
184 |
185 |
186 | #endif // RemoteXYWireStream_h
--------------------------------------------------------------------------------