├── README-de.md
├── README-ru.md
├── README.md
└── fx1sample
├── common.h
├── fx1.h
├── fx1parser.ino
├── fx1sample.ino
└── fx1utils.ino
/README-de.md:
--------------------------------------------------------------------------------
1 | [English](README.md) ∙ [Русский](README-ru.md) ∙ [Deutsch](README-de.md)
2 | # fx1-arduino-parser
3 |
4 | PLease help me translate README.md file to Deutsch. Thanks!
5 |
--------------------------------------------------------------------------------
/README-ru.md:
--------------------------------------------------------------------------------
1 | [English](README.md) ∙ [Русский](README-ru.md)
2 | # fx1-arduino-parser
3 | Подключаем Arduino к ROBO Pro через USB
4 |
5 | [](http://www.youtube.com/watch?v=otV3sn2Q770)
6 |
7 | После загрузки скетча fx1-arduino-parser.ino плата Arduino ведет себя как контроллер ROBO TX в режиме "Online". Вы составляете алгоритм в виде блок-схемы в ROBO Pro, а Arduino берет на себя взаимодействие с объектом управления. Таким образом fx1-arduino-parser можно использовать для изучения алгоритмического программирования в образовательных проектах.
8 |
9 | Если у вас появятся новые идеи насчет использования этого проекта - буду рад получить ваш отзыв. Весь исходный код проекта открыт для свободного использования. Мир! Упчк!
10 |
11 | ## Содержание
12 | * [Системные требования](#requirements)
13 | * [Использование по назначению](#how-to-use)
14 | * [Привязка портов Arduino к ROBO Pro](#pin-mapping)
15 | * [Решение проблемы с автоматической перезагрузкой Arduino](#solution-for-reboot)
16 | * [Ссылки](#ссылки)
17 | * [История проекта](#история-проекта)
18 | * [Лицензия](#лицензия)
19 |
20 | ## Системные требования
21 | * ROBO Pro версия 4.6.6
22 | * Интрефейс USB
23 |
24 | ## Использование по назначению
25 | 1. Загрузите [свежий релиз](https://github.com/mr-kubikus/fx1-arduino-parser/releases) проекта на свой компьютер.
26 | 2. Распакуйте архив fx1-arduino-parser.zip в папку с проектами для Arduino.
27 | 3. Откройте проект fx1-arduino-parser.ino в Arduino IDE и скомпилируйте и загрузите в Arduino.
28 | 4. Определите - какой последовательный порт использует плата Arduino.
29 | 5. Запустите ROBO Pro.
30 | 6. Укажите настройки подключения к контроллеру: порт - USB, тип контроллера - ROBO TX.
31 | 7. Укажите тип подключения - Bluetooth и выберите порт, к которому подкулючена плата Arduino (см. шаг 4).
32 | 8. Составьте блок схему алгоритма.
33 | 9. Запустите проект в режиме "Онлайн".
34 |
35 | ## Привязка портов Arduino к ROBO Pro
36 | ### Входы
37 | | RP pin | Arduino pin | RP pin mode |
38 | |:------------- |:-----------:|:-----------:|
39 | | I1 | 2 | Digital |
40 | | I2 | 3 | Digital |
41 | | I3 | 4 | Digital |
42 | | I4 | A0 | Analog |
43 | | I5 | A1 | Analog |
44 | | I6 | A2 | Analog |
45 | | I7 | A3 | Analog |
46 | | I8 | A4 | Analog |
47 |
48 |
49 | ### Выходы
50 | | RP pin | Arduino pin | RP pin mode |
51 | |:------------- |:-----------:|:------------:|
52 | | O1 | 6 | Digital |
53 | | O2 | 7 | Digital |
54 | | O3 | 8 | Digital |
55 | | O4 | 9 | Analog (0-8) |
56 | | O5 | 10 | Analog (0-8) |
57 | | O6 | 11 | Analog (0-8) |
58 | | O7 | 12 | Digital |
59 | | O8 | 13 | Digital |
60 |
61 | ## Решение проблемы с автоматической перезагрузкой Arduino
62 | Если вы используете плату Arduino UNO или клон, то возможна следующая проблема. Когда ROBO Pro открывает порт - Arduino перезагружается. Это может приводить к появленияю сообщения "Timeout" в ROBO Pro. Для устранения этой проблемы надо отключить автоматическу перезагрузку Arduino UNO согласно рекомендациям с сайта [playground.arduino.cc](https://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection/).
63 |
64 | ## Ссылки
65 | 1. [Исходное обсуждение на форуме ftcommunity.de forum](https://forum.ftcommunity.de/viewtopic.php?f=8&t=1655).
66 | 2. [Загрузка ROBO Pro с сайта fischertechnik.de](https://www.fischertechnik.de/de-de/apps-und-software/software-archiv).
67 |
68 | ## История проекта
69 | V0.3 - 11.08.2016. Changed version.firmware.part.b by one to make it compatible with ROBO Pro 4.2.3.
70 |
71 | V0.2 - 03.09.2015. Changed output pins map. Now Arduino's pins 6-13 coresponds to ROBO TX pins O1-O8.
72 | Changed input pins map. Now Arduino's pins A3-A4 coresponds to ROBO TX pins I7 and I8.
73 | This version tested with ROBO Pro 4.1.8, Arduino IDE 1.0.6 and ARUDINO UNO R3 board.
74 |
75 | V0.1 - 03.01.2013. This version tested with ROBO Pro 3.2.0, Arduino IDE 1.0.3 and ARUDINO UNO R3 board.
76 |
77 | ## Лицензия
78 | Все содержание данного репозитория распространяется под лицензией [Creative Commons Share-alike 3.0](http://creativecommons.org/licenses/by-sa/3.0/).
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [English](README.md) ∙ [Русский](README-ru.md) ∙ [Deutsch](README-de.md)
2 | # fx1-arduino-parser
3 | Arduino sketch for communicating with ROBO Pro software over USB.
4 |
5 | [](http://www.youtube.com/watch?v=otV3sn2Q770)
6 |
7 | The fx1-arduino-parser is a component that may be useful for a variety of projects, including educational tools. I want developers to be able to play with fx1-arduino-parser, give feedback, and think of novel uses for it. All the code is free and open source. Enjoy!
8 |
9 | ## Table of Contents
10 | * [System requirements](#requirements)
11 | * [How to use it](#how-to-use)
12 | * [Pin mapping](#pin-mapping)
13 | * [Solution for automatic reboot problem](#solution-for-reboot)
14 | * [Links](#links)
15 | * [Version history](#history)
16 | * [License](#license)
17 |
18 | ## System requirements
19 | * ROBO Pro version - 4.6.6
20 | * USB Interface
21 |
22 | ## How to use it
23 | 1. Download latest fx1-arduino-parser release.
24 | 2. Open in Arduino IDE and Upload fx1-arduino-parser to board.
25 | 3. Find which serial port used by Arduino.
26 | 4. Start ROBO Pro.
27 | 5. Setup Connection and Controller model: USB and ROBO TX.
28 | 6. Choose Bluetooth connection type and then select COM port from STEP #3.
29 | 7. Design flow-chart.
30 | 8. Run it in Online mode.
31 |
32 | ## Pin mapping
33 | ### Inputs
34 | | RP pin | Arduino pin | RP pin mode |
35 | |:------------- |:-----------:|:-----------:|
36 | | I1 | 2 | Digital |
37 | | I2 | 3 | Digital |
38 | | I3 | 4 | Digital |
39 | | I4 | A0 | Analog |
40 | | I5 | A1 | Analog |
41 | | I6 | A2 | Analog |
42 | | I7 | A3 | Analog |
43 | | I8 | A4 | Analog |
44 |
45 |
46 | ### Оutputs
47 | | RP pin | Arduino pin | RP pin mode |
48 | |:------------- |:-----------:|:------------:|
49 | | O1 | 6 | Digital |
50 | | O2 | 7 | Digital |
51 | | O3 | 8 | Digital |
52 | | O4 | 9 | Analog (0-8) |
53 | | O5 | 10 | Analog (0-8) |
54 | | O6 | 11 | Analog (0-8) |
55 | | O7 | 12 | Digital |
56 | | O8 | 13 | Digital |
57 |
58 | ## Solution for automatic reboot problem
59 | The Arduino Uno and Nano auto reboot feature allows to upload a sketch when PC opens the connection. This behaviour leads to "Timeout" message in the ROBO Pro.
60 |
61 | You can disablie the auto reboot feature using recomendations from [playground.arduino.cc](https://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection/).
62 |
63 | ## Links
64 | 1. [Original discussion at the ftcommunity.de forum](https://forum.ftcommunity.de/viewtopic.php?f=8&t=1655).
65 | 2. [ROBO Pro download at the fischertechnik.de](https://www.fischertechnik.de/de-de/apps-und-software/software-archiv).
66 |
67 | ## Version history
68 | V0.3 - 11.08.2016. Changed version.firmware.part.b by one to make it compatible with ROBO Pro 4.2.3.
69 |
70 | V0.2 - 03.09.2015. Changed output pins map. Now Arduino's pins 6-13 coresponds to ROBO TX pins O1-O8.
71 | Changed input pins map. Now Arduino's pins A3-A4 coresponds to ROBO TX pins I7 and I8.
72 | This version tested with ROBO Pro 4.1.8, Arduino IDE 1.0.6 and ARUDINO UNO R3 board.
73 |
74 | V0.1 - 03.01.2013. This version tested with ROBO Pro 3.2.0, Arduino IDE 1.0.3 and ARUDINO UNO R3 board.
75 |
76 | ## License
77 | All contents of this repository are released under [Creative Commons Share-alike 3.0](http://creativecommons.org/licenses/by-sa/3.0/).
78 |
--------------------------------------------------------------------------------
/fx1sample/common.h:
--------------------------------------------------------------------------------
1 | #ifndef _COMMON_H_
2 | #define _COMMON_H_
3 |
4 | // Declaration of data types
5 |
6 | typedef signed char CHAR8;
7 | typedef unsigned char UCHAR8;
8 |
9 | typedef unsigned char BOOL8; // Boolean variable (should be TRUE or FALSE)
10 | typedef unsigned short BOOL16;
11 | typedef unsigned long BOOL32;
12 |
13 | typedef signed char INT8;
14 | typedef short INT16;
15 | typedef signed long INT32;
16 |
17 | typedef unsigned char UINT8;
18 | typedef unsigned short UINT16;
19 | typedef unsigned long UINT32;
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/fx1sample/fx1.h:
--------------------------------------------------------------------------------
1 | #ifndef _FX1_H_
2 | #define _FX1_H_
3 |
4 | #include "common.h"
5 |
6 | #define TX_BAUD 38400
7 | #define BUF_MAXLEN 256
8 |
9 | //
10 | // Constantas from ROBO_TX_FW.h
11 | //
12 | #define N_CNT 4 // Number of counters
13 | #define N_PWM_CHAN 8 // Number of PWM channels
14 | #define N_MOTOR 4 // Number of motors
15 | #define N_UNI 8 // Number of universal inputs
16 |
17 | // 5kOhm range
18 | #define R_MIN 10 // [Ohm]
19 | #define R_MAX 4999 // [Ohm]
20 | #define R_OVR 5000 // [Ohm] overload
21 |
22 | // 10V range
23 | #define U_MIN 0 // [mV]
24 | #define U_MAX 9999 // [mV]
25 | #define U_OVR 10000 // [mV] overload
26 |
27 | // Ultrasonic Sensor range
28 | #define ULTRASONIC_MIN 2 // [cm]
29 | #define ULTRASONIC_MAX 1023 // [cm]
30 | #define ULTRASONIC_OVR 1024 // [cm] overload
31 | #define NO_ULTRASONIC 4096 // Not present
32 |
33 | // Motor outputs PWM values range
34 | #define DUTY_MIN 0
35 | #define DUTY_MAX 512
36 |
37 | // Length of strings
38 | #define DEV_NAME_LEN_MAX 16 // "ROBO TX-xxxxxxxx"
39 | #define BT_ADDR_STR_LEN 17 // "xx:xx:xx:xx:xx:xx"
40 | #define DISPL_MSG_LEN_MAX 98 // Max. length of a pop-up display message
41 |
42 | // Number of Bluetooth channels
43 | #define BT_CNT_MAX 8
44 |
45 | // Allowed values for channel index are 1...8
46 | #define BT_CHAN_IDX_MIN 1
47 | #define BT_CHAN_IDX_MAX 8
48 |
49 | #define BT_ADDR_LEN 6 // Bluetooth address length
50 | #define BT_MSG_LEN 16 // Max. Bluetooth message length
51 |
52 | // Identifiers of the Transfer Area
53 | enum ta_id_e
54 | {
55 | TA_LOCAL = 0, // Transfer Area for local Controller. Corresponds to the Controller
56 | // on which program is currently running in download (local) mode or
57 | // to the remotely controlled Controller (seen from controlled device,
58 | // not from controlling device) in online mode.
59 | TA_EXT_1, // Transfer Area for Extension 1 Controller
60 | TA_EXT_2, // Transfer Area for Extension 2 Controller
61 | TA_EXT_3, // Transfer Area for Extension 3 Controller
62 | TA_EXT_4, // Transfer Area for Extension 4 Controller
63 | TA_EXT_5, // Transfer Area for Extension 5 Controller
64 | TA_EXT_6, // Transfer Area for Extension 6 Controller
65 | TA_EXT_7, // Transfer Area for Extension 7 Controller
66 | TA_EXT_8, // Transfer Area for Extension 8 Controller
67 | TA_COUNT // Number of Transfer Areas in array = 9
68 | };
69 |
70 | #define N_EXT (TA_COUNT - 1) // Number of extension Controllers = 8
71 |
72 | //
73 | // FishX1 command codes
74 | //
75 | enum eX1CmdCode {
76 | CMD_001 = 1,
77 | CMD_001_REPLY = 101, // 0x65
78 | CMD_002 = 2,
79 | CMD_002_REPLY = 102, // 0x66
80 | CMD_005 = 5,
81 | CMD_005_REPLY = 105, // 0x69
82 | CMD_006 = 6,
83 | CMD_006_REPLY = 106, // 0x6A
84 | CMD_007 = 7,
85 | CMD_007_REPLY = 107, // 0x6B
86 | };
87 |
88 | //
89 | // Program information, 8 bytes
90 | //
91 | typedef struct
92 | {
93 | unsigned char name_ptr[4]; // Name of a program with a full path, for example, "/ramdisk/Program_1"
94 | unsigned char state; // See enum pgm_state_e
95 | char dummy[3];
96 | } PGM_INFO;
97 |
98 | //
99 | // Bluetooth connection status structure, 8 bytes
100 | //
101 | typedef struct
102 | {
103 | UINT16 conn_state; // See enum BtConnState
104 | BOOL16 is_listen; // If TRUE - BT channel is waiting for incoming connection (listening)
105 | BOOL16 is_receive; // If TRUE - BT channel is ready to receive incoming messages
106 | UINT16 link_quality; // 0...31, 0 - the worst, 31 - the best signal quality
107 | } BT_STATUS;
108 |
109 | //
110 | // Version structure definition, 4 bytes
111 | //
112 | typedef union
113 | {
114 | UINT32 abcd;
115 | struct
116 | {
117 | UCHAR8 a;
118 | UCHAR8 b;
119 | UCHAR8 c;
120 | UCHAR8 d;
121 | } part;
122 | } FT_VER;
123 |
124 | //
125 | // Versions of hardware and firmware components, 16 bytes
126 | //
127 | typedef struct
128 | {
129 | FT_VER hardware; // Version of hardware (hardware.part.a = 'A' or 'B' or 'C')
130 | FT_VER firmware; // Version of firmware ("V %d.%02d, DLL %d", firmware.part.c,
131 | // firmware.part.d, firmware.part.b)
132 | FT_VER ta; // Version of transfer area ("V %d.%02d", ta.part.c, ta.part.d)
133 | char reserved[4];
134 | } FT_VERSION;
135 |
136 | //
137 | // Structures for Transfer Area
138 | //
139 | //
140 | // Info structure, 64 bytes
141 | //
142 | typedef struct
143 | {
144 | char device_name[DEV_NAME_LEN_MAX + 1]; // Controller name
145 | char bt_addr[BT_ADDR_STR_LEN + 1]; // Bluetooth address as a string
146 | char reserved;
147 | UINT32 ta_array_start_addr;
148 | UINT32 pgm_area_start_addr;
149 | UINT32 pgm_area_size;
150 | FT_VERSION version;
151 | } TA_INFO;
152 |
153 | //
154 | // State structure, 100 bytes
155 | //
156 | typedef struct
157 | {
158 | // Used by local program
159 | BOOL8 pgm_initialized;
160 | char reserved_1[7];
161 |
162 | // Public state info
163 | BOOL8 dev_mode; // See enum dev_mode_e
164 | UINT8 id; // Should be increased by 1 each time something (except id fields and btstatus)
165 | // is changed in this state structure
166 | UINT8 info_id; // Should be increased by 1 each time something is changed in info structure
167 | UINT8 config_id; // Should be increased by 1 each time something is changed in config structure
168 | BOOL8 ext_dev_connect_state[N_EXT]; // See enum ext_dev_connect_state_e
169 | BT_STATUS btstatus[BT_CNT_MAX]; // Status of Bluetooth connections
170 | char reserved_2[8];
171 | PGM_INFO local_pgm; // Corresponds to the program currently being in the program memory
172 | } TA_STATE;
173 |
174 | //
175 | // Input structure, 48 bytes
176 | //
177 | typedef struct
178 | {
179 | INT16 uni[N_UNI]; // Current values of the universal inputs
180 | UINT8 cnt_in[N_CNT]; // Current levels (0 or 1) on the counter inputs according
181 | // to their configuration (normal or inverse)
182 | INT16 counter[N_CNT]; // Current values of the counter inputs
183 | INT16 display_button_left; // Number of milliseconds during which the left display button
184 | // is being kept pressed
185 | INT16 display_button_right; // Number of milliseconds during which the right display button
186 | // is being kept pressed
187 | char reserved[16];
188 | } TA_INPUT;
189 |
190 | //
191 | // Output structure, 44 bytes
192 | //
193 | typedef struct
194 | {
195 | unsigned short cnt_reset_cmd_id[N_CNT]; // Counter reset requests (should be increased by 1 each time
196 | // counter reset is needed)
197 | unsigned char master[N_MOTOR]; // If not 0, synchronize this channel with the given channel
198 | // (1:channel 0, ...)
199 | short duty[N_PWM_CHAN]; // Selected motor outputs PWM values
200 | unsigned short distance[N_MOTOR]; // Selected distance (counter value) at which motor shall stop
201 | unsigned short motor_ex_cmd_id[N_MOTOR]; // Should be increased by 1 each time settings for extended
202 | // motor control mode (duty and/or distance) are changed
203 | } TA_OUTPUT;
204 |
205 | //
206 | // CMD=0x02 Request structure
207 | //
208 | typedef struct {
209 | UINT32 TAId;
210 | TA_OUTPUT X1Data;
211 | } CMD002_REQ;
212 |
213 | //
214 | // CMD=0x02 Reply structure
215 | //
216 | typedef struct {
217 | UINT32 TAId;
218 | TA_INPUT X1Data;
219 | } CMD002_REPLY;
220 |
221 | //
222 | // CMD=0x05 Reply structure
223 | //
224 | typedef struct {
225 | UINT32 TAId;
226 | } CMD005_REPLY;
227 |
228 | //
229 | // CMD=0x06 Reply structure
230 | //
231 | typedef struct {
232 | UINT32 TAId;
233 | TA_INFO X1Data;
234 | } CMD006_REPLY;
235 |
236 | //
237 | // CMD=0x07 Reply structure
238 | //
239 | typedef struct {
240 | UINT32 TAId;
241 | TA_STATE X1Data;
242 | } CMD007_REPLY;
243 |
244 |
245 | enum eX1FSMState {
246 | UNKNOWN_STATE = 0,
247 | FSM_WAIT_STX,
248 | FSM_WAIT_55,
249 | FSM_WAIT_L_1,
250 | FSM_WAIT_L_2,
251 | FSM_WAIT_DATA,
252 | FSM_WAIT_CS_1,
253 | FSM_WAIT_CS_2,
254 | FSM_WAIT_ETX
255 | };
256 |
257 | enum eSHFSMState {
258 | S_STATE_UNKNOWN = 0,
259 | GET_0D_START,
260 | GET_67,
261 | GET_0D_END
262 | };
263 |
264 | unsigned char rxData[BUF_MAXLEN];
265 | unsigned char txData[BUF_MAXLEN];
266 | unsigned char tmpData[BUF_MAXLEN];
267 |
268 | unsigned int x1FSMState;
269 | unsigned int x1SHFSMState;
270 |
271 | unsigned char *pDataPtr;
272 | unsigned short nRXDataLen;
273 |
274 | unsigned short nX1DataLen;
275 | unsigned short nX1DataCnt;
276 | unsigned short nX1CheckSum;
277 | unsigned short nCheckSum;
278 |
279 | unsigned short nX1TicketId;
280 | unsigned short nX1SessionId;
281 |
282 | #endif
283 |
284 |
--------------------------------------------------------------------------------
/fx1sample/fx1parser.ino:
--------------------------------------------------------------------------------
1 | //
2 | // ROBO Pro to Arduino pins map:
3 | //
4 |
5 | // Outputs
6 | const int OUT1 = 6; //
7 | const int OUT2 = 7; //
8 | const int OUT3 = 8; //
9 | const int OUT4 = 9; // PWM
10 | const int OUT5 = 10; // PWM
11 | const int OUT6 = 11; // PWM
12 | const int OUT7 = 12; //
13 | const int OUT8 = 13; //
14 |
15 | // Inputs
16 | const int IN1 = 2; //
17 | const int IN2 = 3; //
18 | const int IN3 = 4; //
19 | const int IN4 = A0; // Analog
20 | const int IN5 = A1; // Analog
21 | const int IN6 = A2; // Analog
22 | const int IN7 = A3; // Analog
23 | const int IN8 = A4; // Analog
24 |
25 | void fx1ParserInit()
26 | {
27 | x1FSMState = FSM_WAIT_STX;
28 | x1SHFSMState = GET_0D_START;
29 | nX1TicketId = 0;
30 | nX1SessionId = 0;
31 |
32 | // Configure the output pins:
33 | pinMode(OUT1, OUTPUT);
34 | pinMode(OUT2, OUTPUT);
35 | pinMode(OUT3, OUTPUT);
36 | pinMode(OUT4, OUTPUT);
37 | pinMode(OUT5, OUTPUT);
38 | pinMode(OUT6, OUTPUT);
39 | pinMode(OUT7, OUTPUT);
40 | pinMode(OUT8, OUTPUT);
41 |
42 | digitalWrite(OUT1, LOW);
43 | digitalWrite(OUT2, LOW);
44 | digitalWrite(OUT3, LOW);
45 | digitalWrite(OUT4, LOW);
46 | digitalWrite(OUT5, LOW);
47 | digitalWrite(OUT6, LOW);
48 | digitalWrite(OUT7, LOW);
49 | digitalWrite(OUT8, LOW);
50 |
51 | // Configure the input pins:
52 | pinMode(IN1, INPUT_PULLUP);
53 | pinMode(IN2, INPUT_PULLUP);
54 | pinMode(IN3, INPUT_PULLUP);
55 | }
56 |
57 | void fx1ParserParse(unsigned char symbol)
58 | {
59 | switch (x1SHFSMState) {
60 | case GET_0D_START:
61 | if ( symbol != 0x0D ) break;
62 | x1SHFSMState = GET_67;
63 | break;
64 |
65 | case GET_67:
66 | if ( symbol != 0x67 ) {
67 | x1SHFSMState = GET_0D_START;
68 | break;
69 | }
70 | x1SHFSMState = GET_0D_END;
71 | break;
72 |
73 | case GET_0D_END:
74 | if ( symbol != 0x0D ) break;
75 | sendShellData();
76 | x1SHFSMState = GET_0D_START;
77 | break;
78 |
79 | default:
80 | break;
81 | }
82 |
83 | switch (x1FSMState) {
84 | case FSM_WAIT_STX:
85 | if ( symbol == 0x02 ) {
86 | nRXDataLen = 0;
87 | pDataPtr = rxData;
88 | *(pDataPtr) = symbol;
89 | nRXDataLen++;
90 | x1FSMState = FSM_WAIT_55;
91 | break;
92 | }
93 | break;
94 |
95 | case FSM_WAIT_55:
96 | if ( symbol != 0x55 ) {
97 | x1FSMState = FSM_WAIT_STX;
98 | break;
99 | }
100 | *(pDataPtr+nRXDataLen) = symbol;
101 | nRXDataLen++;
102 | nX1DataLen = 0;
103 | nCheckSum = 0;
104 | x1FSMState = FSM_WAIT_L_1;
105 | break;
106 |
107 | case FSM_WAIT_L_1:
108 | nX1DataLen = ((symbol << 8) & 0xFF00);
109 | nCheckSum += symbol;
110 | *(pDataPtr+nRXDataLen) = symbol;
111 | nRXDataLen++;
112 | x1FSMState = FSM_WAIT_L_2;
113 | break;
114 |
115 | case FSM_WAIT_L_2:
116 | nX1DataLen += symbol;
117 | nCheckSum += symbol;
118 | *(pDataPtr+nRXDataLen) = symbol;
119 | nRXDataLen++;
120 | nX1DataCnt = 0;
121 | x1FSMState = FSM_WAIT_DATA;
122 | break;
123 |
124 | case FSM_WAIT_DATA:
125 | nCheckSum += symbol;
126 | *(pDataPtr+nRXDataLen) = symbol;
127 | nRXDataLen++;
128 | nX1DataCnt++;
129 |
130 | if ( nX1DataCnt == nX1DataLen )
131 | x1FSMState = FSM_WAIT_CS_1;
132 | break;
133 |
134 | case FSM_WAIT_CS_1:
135 | nX1CheckSum = ((symbol << 8) & 0xFF00);
136 | x1FSMState = FSM_WAIT_CS_2;
137 | break;
138 |
139 | case FSM_WAIT_CS_2:
140 | nX1CheckSum += symbol;
141 | x1FSMState = FSM_WAIT_ETX;
142 | break;
143 |
144 | case FSM_WAIT_ETX:
145 | if ( symbol != 0x03 ) {
146 | x1FSMState = FSM_WAIT_STX;
147 | return;
148 | }
149 |
150 | nCheckSum = (~nCheckSum) + 1;
151 | if ( nCheckSum != nX1CheckSum ) {
152 | x1FSMState = FSM_WAIT_STX;
153 | return;
154 | }
155 |
156 | //fx1ParserProcPacket(pDataPtr+CMD_HEAD_OFFS, nRXDataLen);
157 | fx1ParserProcPacket(pDataPtr, nRXDataLen);
158 |
159 | x1FSMState = FSM_WAIT_STX;
160 | break;
161 |
162 | default:
163 | break;
164 | }
165 | }
166 |
167 | //
168 | // Execute callback functions according to command code CMD in received packet.
169 | //
170 | void fx1ParserProcPacket(unsigned char *pData, int nDataLength)
171 | {
172 | short nCmd = get32BitLE(pData+16);
173 | short nItems = get32BitLE(pData+20);
174 |
175 | nX1TicketId = get16BitLE(pData+12);
176 |
177 | //
178 | // Select and call reply function for received CMD code
179 | //
180 | switch(nCmd) {
181 | case CMD_001 : CMD001Reply(nItems, pData+24);
182 | break;
183 |
184 | case CMD_002 : CMD002Reply(nItems, pData+24);
185 | break;
186 |
187 | case CMD_005 : CMD005Reply(nItems, pData+24);
188 | break;
189 |
190 | case CMD_006 : CMD006Reply(nItems, pData+24);
191 | break;
192 |
193 | case CMD_007 : CMD007Reply(nItems, pData+24);
194 | break;
195 |
196 | default:
197 | break;
198 | }
199 |
200 | }
201 |
202 | void CMD001Reply(short nItems, unsigned char *data)
203 | {
204 | sendX1Data(txData, CMD_001_REPLY, 0, (unsigned char*)NULL, 0);
205 | }
206 |
207 | void CMD002Reply(short nItems, unsigned char *data)
208 | {
209 | CMD002_REQ *request = (CMD002_REQ *) data ;
210 |
211 | if (request->X1Data.duty[0] != 0) {
212 | digitalWrite(OUT1, HIGH);
213 | } else {
214 | digitalWrite(OUT1, LOW);
215 | }
216 |
217 | if (request->X1Data.duty[1] != 0) {
218 | digitalWrite(OUT2, HIGH);
219 | } else {
220 | digitalWrite(OUT2, LOW);
221 | }
222 |
223 | if (request->X1Data.duty[2] != 0) {
224 | digitalWrite(OUT3, HIGH);
225 | } else {
226 | digitalWrite(OUT3, LOW);
227 | }
228 |
229 | analogWrite(OUT4, constrain(request->X1Data.duty[3] / 2 , 0, 255));
230 | analogWrite(OUT5, constrain(request->X1Data.duty[4] / 2 , 0, 255));
231 | analogWrite(OUT6, constrain(request->X1Data.duty[5] / 2 , 0, 255));
232 |
233 | if (request->X1Data.duty[6] != 0) {
234 | digitalWrite(OUT7, HIGH);
235 | } else {
236 | digitalWrite(OUT7, LOW);
237 | }
238 |
239 | if (request->X1Data.duty[7] != 0) {
240 | digitalWrite(OUT8, HIGH);
241 | } else {
242 | digitalWrite(OUT8, LOW);
243 | }
244 |
245 | CMD002_REPLY *reply = (CMD002_REPLY *) data;
246 |
247 | memset((unsigned char*)reply, 0, sizeof(CMD002_REPLY));
248 | reply->TAId = TA_LOCAL;
249 | reply->X1Data.uni[0]=digitalRead(IN1);
250 | reply->X1Data.uni[1]=digitalRead(IN2);
251 | reply->X1Data.uni[2]=digitalRead(IN3);
252 | reply->X1Data.uni[3]=map(analogRead(IN4), 0, 1023, 0, 500);
253 | reply->X1Data.uni[4]=map(analogRead(IN5), 0, 1023, 0, 500);
254 | reply->X1Data.uni[5]=map(analogRead(IN6), 0, 1023, 0, 500);
255 | reply->X1Data.uni[6]=map(analogRead(IN7), 0, 1023, 0, 500);
256 | reply->X1Data.uni[7]=map(analogRead(IN8), 0, 1023, 0, 500);
257 |
258 | sendX1Data(txData, CMD_002_REPLY, 1, (unsigned char*)reply, sizeof(CMD002_REPLY));
259 | }
260 |
261 | void CMD005Reply(short nItems, unsigned char *data)
262 | {
263 | CMD005_REPLY *reply = (CMD005_REPLY *) data;
264 |
265 | memset((unsigned char*)reply, 0, sizeof(CMD005_REPLY));
266 | reply->TAId = TA_LOCAL;
267 | sendX1Data(txData, CMD_005_REPLY, 1, (unsigned char*)reply, sizeof(CMD005_REPLY));
268 | }
269 |
270 | void CMD006Reply(short nItems, unsigned char *data)
271 | {
272 | CMD006_REPLY *reply = (CMD006_REPLY *) tmpData;
273 |
274 | memset((unsigned char*)reply, 0, sizeof(CMD006_REPLY));
275 | reply->TAId = TA_LOCAL;
276 | sprintf(reply->X1Data.device_name, "ROBO TX-000");
277 | sprintf(reply->X1Data.bt_addr, "00:00:00:00:00:00");
278 |
279 | reply->X1Data.ta_array_start_addr = 0; // Sniffed value 0x20000204
280 | reply->X1Data.pgm_area_start_addr = 0; // Sniffed value 0x30700000
281 | reply->X1Data.pgm_area_size = 0; // Sniffed value 0x000d0000
282 |
283 | reply->X1Data.version.hardware.part.a = 0x43; // 67
284 | reply->X1Data.version.hardware.part.b = 0x00;
285 | reply->X1Data.version.hardware.part.c = 0x00;
286 | reply->X1Data.version.hardware.part.d = 0x00;
287 |
288 | reply->X1Data.version.firmware.part.a = 0x00; // 0
289 | reply->X1Data.version.firmware.part.b = 0x06; // 6
290 | reply->X1Data.version.firmware.part.c = 0x01; // 1
291 | reply->X1Data.version.firmware.part.d = 0x1E; // 30
292 |
293 | reply->X1Data.version.ta.part.a = 0x01;
294 | reply->X1Data.version.ta.part.b = 0x01;
295 | reply->X1Data.version.ta.part.c = 0x01;
296 | reply->X1Data.version.ta.part.d = 0x08;
297 |
298 | sendX1Data(txData, CMD_006_REPLY, 1, (unsigned char*)reply, sizeof(CMD006_REPLY));
299 | }
300 |
301 | void CMD007Reply(short nItems, unsigned char *data)
302 | {
303 | CMD006_REPLY *reply = (CMD006_REPLY *) tmpData;
304 |
305 | memset((unsigned char*)reply, 0, sizeof(CMD006_REPLY));
306 | reply->TAId = TA_LOCAL;
307 |
308 | sendX1Data(txData, CMD_007_REPLY, 1, (unsigned char*)reply, 28);
309 | }
310 |
311 | void sendShellData(void)
312 | {
313 | short ii=0;
314 |
315 | sprintf((char*)txData, "\r\nROBO TX-000/USB>get_ser_num\r\n0000000001\r\nROBO TX-000/USB>");
316 |
317 | while (ii < 0x3B) {
318 | Serial.write(txData[ii]);
319 | ii++;
320 | }
321 | }
322 |
323 | void sendX1Data(UINT8 *pPacket, int replyID, short items, unsigned char *pData, short dataLength)
324 | {
325 | int packetLength = 0;
326 | UINT16 nCheckSum = 0;
327 |
328 | //
329 | // Fill the packet structure with data according FishX1 protocol structure from PDF
330 | //
331 | // Set STX + 0x55
332 | *(pPacket+0) = 0x02;
333 | *(pPacket+1) = 0x55;
334 | packetLength += 2;
335 |
336 | // Set Total length
337 | set16BitBE(pPacket+2, dataLength+20);
338 | packetLength += 2;
339 |
340 | // Set FROM
341 | set32BitLE(pPacket+4, 2);
342 | packetLength += 4;
343 |
344 | // Set TO
345 | set32BitLE(pPacket+8, 2);
346 | packetLength += 4;
347 |
348 | // Set TID
349 | set16BitLE(pPacket+12, nX1TicketId);
350 | packetLength += 2;
351 |
352 | // Set SID
353 | set16BitLE(pPacket+14, nX1SessionId);
354 | packetLength += 2;
355 |
356 | // Set Command Code
357 | set32BitLE(pPacket+16, replyID);
358 | packetLength += 4;
359 |
360 | // Set Number of following Fish.X1 data structures
361 | set32BitLE(pPacket+20, items);
362 | packetLength += 4;
363 |
364 | // Set TA ID and Fish.X1 data
365 | memcpy((void*)(pPacket+24), (void*)pData, dataLength);
366 | packetLength += dataLength;
367 |
368 | // Set CheckSum
369 | nCheckSum = calcCheckSum(pPacket+2, packetLength-2);
370 | set16BitBE(pPacket+packetLength, nCheckSum);
371 | packetLength += 2;
372 |
373 | // Set ETX
374 | *(pPacket+packetLength) = 0x03;
375 | packetLength++;
376 |
377 | short dataCounter=0;
378 |
379 | while (dataCounter < packetLength) {
380 | Serial.write(pPacket[dataCounter]);
381 | dataCounter++;
382 | }
383 |
384 | return;
385 | }
386 |
--------------------------------------------------------------------------------
/fx1sample/fx1sample.ino:
--------------------------------------------------------------------------------
1 | //
2 | // Sample sketch for the Fish.X1 protocol parser
3 | // For more information please visit:
4 | // https://github.com/mr-kubikus/fx1-arduino-parser
5 | // http://forum.ftcommunity.de/viewtopic.php?f=8&t=1655
6 | //
7 | // Thanks to Ad2 for helpful information
8 | // Thanks to https://www.facebook.com/fischertechnik.ru for support
9 | //
10 |
11 | #include "fx1.h"
12 |
13 | void setup()
14 | {
15 | // Initialize parser
16 | fx1ParserInit();
17 |
18 | // Initialize UART
19 | // ROBO TX works at 38400,8,n,1
20 | while(!Serial);
21 | Serial.begin(38400);
22 |
23 | }
24 |
25 | void loop()
26 | {
27 | unsigned char symbol = 0;
28 |
29 | // Check UART and read one symbol
30 | if (Serial.available() > 0 ) {
31 | symbol = Serial.read();
32 | } else {
33 | return;
34 | }
35 |
36 | // Parse FishX1 protocol
37 | fx1ParserParse(symbol);
38 | }
39 |
--------------------------------------------------------------------------------
/fx1sample/fx1utils.ino:
--------------------------------------------------------------------------------
1 | //
2 | // 16 bit data access
3 | //
4 | void set16BitLE(unsigned char *pData, UINT16 value)
5 | {
6 | *(pData+0) = value & 0xFF;
7 | *(pData+1) = (value >> 8) & 0xFF;
8 | }
9 |
10 | UINT16 get16BitLE(unsigned char *pData)
11 | {
12 | UINT16 value = 0;
13 | value = *(pData+0);
14 | value += (*(pData+1) << 8) & 0xFF00;
15 | return value;
16 | }
17 |
18 | void set16BitBE(unsigned char *pData, UINT16 value)
19 | {
20 | *(pData+0) = (value >> 8) & 0xFF;
21 | *(pData+1) = value & 0xFF;
22 | }
23 |
24 | UINT16 get16BitBE(unsigned char *pData)
25 | {
26 | UINT16 value = 0;
27 | value = (*(pData+0) << 8) & 0xFF00;
28 | value += *(pData+1);
29 | return value;
30 | }
31 |
32 | //
33 | // 32 bit data access
34 | //
35 | void set32BitLE(unsigned char *pData, UINT32 value)
36 | {
37 | *(pData+0) = value & 0xFF;
38 | *(pData+1) = (value >> 8) & 0xFF;
39 | *(pData+2) = (value >> 16) & 0xFF;
40 | *(pData+3) = (value >> 24) & 0xFF;
41 | }
42 |
43 | UINT32 get32BitLE(unsigned char *pData)
44 | {
45 | UINT32 value = 0;
46 | value = *(pData+0);
47 | value += *(pData+1) << 8;
48 | value += *(pData+2) << 16;
49 | value += *(pData+3) << 24;
50 | return value;
51 | }
52 |
53 | void set32BitBE(unsigned char *pData, UINT32 value)
54 | {
55 | *(pData+0) = (value >> 24) & 0xFF;
56 | *(pData+1) = (value >> 16) & 0xFF;
57 | *(pData+2) = (value >> 8) & 0xFF;
58 | *(pData+3) = value & 0xFF;
59 | }
60 |
61 |
62 | unsigned short calcCheckSum(unsigned char Message[], int nBytes)
63 | {
64 | unsigned short sum = 0;
65 |
66 | while(nBytes-- > 0) {
67 | sum += *(Message++);
68 | }
69 | sum = (~sum);
70 | sum++;
71 |
72 | return sum;
73 | }
74 |
75 |
--------------------------------------------------------------------------------