├── 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 | [![Демонстрация ROBOPro и Arduino](http://img.youtube.com/vi/otV3sn2Q770/0.jpg)](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 | [![ROBOPro with Arduino demo](http://img.youtube.com/vi/otV3sn2Q770/0.jpg)](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 | --------------------------------------------------------------------------------