First Commit

Dependencies:   mbed Crypto_light mbed-rtos

Spin it 2 win it

Committer:
andrebharath
Date:
Tue Mar 20 14:49:51 2018 +0000
Revision:
17:80159ace5ddf
Parent:
15:bd303ab8a21f
Child:
18:05e5d280a082
Controlling motor torque

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TrebleStick 0:88c3d6c8a4eb 1 #include "mbed.h"
andrebharath 3:2e32d7974962 2 #include "Crypto_light/hash/SHA256.h"
andrebharath 3:2e32d7974962 3 #include "mbed-rtos/rtos/rtos.h"
TrebleStick 0:88c3d6c8a4eb 4
TrebleStick 0:88c3d6c8a4eb 5 //Photointerrupter input pins
TrebleStick 0:88c3d6c8a4eb 6 #define I1pin D2
TrebleStick 0:88c3d6c8a4eb 7 #define I2pin D11
TrebleStick 0:88c3d6c8a4eb 8 #define I3pin D12
andrebharath 9:ecef1e8cbe3d 9
TrebleStick 0:88c3d6c8a4eb 10 //Incremental encoder input pins
TrebleStick 0:88c3d6c8a4eb 11 #define CHA D7
TrebleStick 12:1b2e2540e4e1 12 #define CHB D8
andrebharath 9:ecef1e8cbe3d 13
TrebleStick 0:88c3d6c8a4eb 14 //Motor Drive output pins //Mask in output byte
TrebleStick 0:88c3d6c8a4eb 15 #define L1Lpin D4 //0x01
TrebleStick 0:88c3d6c8a4eb 16 #define L1Hpin D5 //0x02
TrebleStick 0:88c3d6c8a4eb 17 #define L2Lpin D3 //0x04
TrebleStick 0:88c3d6c8a4eb 18 #define L2Hpin D6 //0x08
TrebleStick 0:88c3d6c8a4eb 19 #define L3Lpin D9 //0x10
TrebleStick 0:88c3d6c8a4eb 20 #define L3Hpin D10 //0x20
TrebleStick 0:88c3d6c8a4eb 21
andrebharath 9:ecef1e8cbe3d 22 #define CHAR_ARR_SIZE 18 //Max length of input codes
andrebharath 17:80159ace5ddf 23 #define MAX_PWM_PERIOD 2000
andrebharath 3:2e32d7974962 24
TrebleStick 0:88c3d6c8a4eb 25 //Mapping from sequential drive states to motor phase outputs
TrebleStick 0:88c3d6c8a4eb 26 /*
TrebleStick 0:88c3d6c8a4eb 27 State L1 L2 L3
TrebleStick 0:88c3d6c8a4eb 28 0 H - L
TrebleStick 0:88c3d6c8a4eb 29 1 - H L
TrebleStick 0:88c3d6c8a4eb 30 2 L H -
TrebleStick 0:88c3d6c8a4eb 31 3 L - H
TrebleStick 0:88c3d6c8a4eb 32 4 - L H
TrebleStick 0:88c3d6c8a4eb 33 5 H L -
TrebleStick 0:88c3d6c8a4eb 34 6 - - -
TrebleStick 0:88c3d6c8a4eb 35 7 - - -
TrebleStick 0:88c3d6c8a4eb 36 */
TrebleStick 0:88c3d6c8a4eb 37 //Drive state to output table
TrebleStick 0:88c3d6c8a4eb 38 const int8_t driveTable[] = {0x12,0x18,0x09,0x21,0x24,0x06,0x00,0x00};
andrebharath 9:ecef1e8cbe3d 39
TrebleStick 0:88c3d6c8a4eb 40 //Mapping from interrupter inputs to sequential rotor states. 0x00 and 0x07 are not valid
TrebleStick 12:1b2e2540e4e1 41 const int8_t stateMap[] = {0x07,0x05,0x03,0x04,0x01,0x00,0x02,0x07};
TrebleStick 0:88c3d6c8a4eb 42 //const int8_t stateMap[] = {0x07,0x01,0x03,0x02,0x05,0x00,0x04,0x07}; //Alternative if phase order of input or drive is reversed
andrebharath 9:ecef1e8cbe3d 43
TrebleStick 0:88c3d6c8a4eb 44 //Phase lead to make motor spin
TrebleStick 0:88c3d6c8a4eb 45 const int8_t lead = 2; //2 for forwards, -2 for backwards
andrebharath 9:ecef1e8cbe3d 46
andrebharath 9:ecef1e8cbe3d 47 //Rotor offset at motor state 0
andrebharath 9:ecef1e8cbe3d 48 int8_t orState = 0;
andrebharath 9:ecef1e8cbe3d 49
andrebharath 17:80159ace5ddf 50 //Set initial torque of 1000
andrebharath 17:80159ace5ddf 51 uint32_t torque = 1000;
andrebharath 17:80159ace5ddf 52
andrebharath 9:ecef1e8cbe3d 53
TrebleStick 12:1b2e2540e4e1 54 enum MSG {MSG_RESET, MSG_HASHCOUNT, MSG_NONCE_OK,
andrebharath 17:80159ace5ddf 55 MSG_OVERFLOW, MSG_ROT_PEN, MSG_MAX_SPD, MSG_NEW_KEY, MSG_INP_ERR,
andrebharath 17:80159ace5ddf 56 MSG_TEST, MSG_TORQUE};
andrebharath 9:ecef1e8cbe3d 57
andrebharath 3:2e32d7974962 58 //Instantiate the serial port
andrebharath 9:ecef1e8cbe3d 59 RawSerial pc(SERIAL_TX, SERIAL_RX);
andrebharath 9:ecef1e8cbe3d 60
andrebharath 9:ecef1e8cbe3d 61 //Status LED
andrebharath 9:ecef1e8cbe3d 62 DigitalOut led1(LED1);
andrebharath 9:ecef1e8cbe3d 63
andrebharath 9:ecef1e8cbe3d 64 //Photointerrupter inputs
andrebharath 9:ecef1e8cbe3d 65 InterruptIn I1(I1pin);
andrebharath 9:ecef1e8cbe3d 66 InterruptIn I2(I2pin);
andrebharath 9:ecef1e8cbe3d 67 InterruptIn I3(I3pin);
andrebharath 9:ecef1e8cbe3d 68
andrebharath 9:ecef1e8cbe3d 69 //Motor Drive outputs
andrebharath 17:80159ace5ddf 70 PwmOut L1L(L1Lpin);
andrebharath 9:ecef1e8cbe3d 71 DigitalOut L1H(L1Hpin);
andrebharath 17:80159ace5ddf 72 PwmOut L2L(L2Lpin);
andrebharath 9:ecef1e8cbe3d 73 DigitalOut L2H(L2Hpin);
andrebharath 17:80159ace5ddf 74 PwmOut L3L(L3Lpin);
andrebharath 9:ecef1e8cbe3d 75 DigitalOut L3H(L3Hpin);
andrebharath 9:ecef1e8cbe3d 76
TrebleStick 0:88c3d6c8a4eb 77
andrebharath 3:2e32d7974962 78
andrebharath 3:2e32d7974962 79 typedef struct {
andrebharath 3:2e32d7974962 80 uint8_t code;
TrebleStick 15:bd303ab8a21f 81 int32_t data;
andrebharath 3:2e32d7974962 82 } message_t ;
andrebharath 3:2e32d7974962 83
andrebharath 3:2e32d7974962 84 Mail<message_t,16> outMessages;
andrebharath 3:2e32d7974962 85
TrebleStick 12:1b2e2540e4e1 86
TrebleStick 15:bd303ab8a21f 87 void putMessage(uint8_t code, int32_t data) {//uint64_t
TrebleStick 12:1b2e2540e4e1 88 message_t *pMessage = outMessages.alloc();
TrebleStick 12:1b2e2540e4e1 89 pMessage->code = code;
TrebleStick 12:1b2e2540e4e1 90 pMessage->data = data;
TrebleStick 12:1b2e2540e4e1 91 outMessages.put(pMessage);
TrebleStick 12:1b2e2540e4e1 92 }
TrebleStick 12:1b2e2540e4e1 93
andrebharath 3:2e32d7974962 94 Thread commOutT;
andrebharath 3:2e32d7974962 95
TrebleStick 12:1b2e2540e4e1 96 void commOutFn() {
andrebharath 3:2e32d7974962 97 while(1) {
andrebharath 3:2e32d7974962 98 osEvent newEvent = outMessages.get();
andrebharath 3:2e32d7974962 99 message_t *pMessage = (message_t*)newEvent.value.p;
TrebleStick 15:bd303ab8a21f 100 pc.printf("Message: [%d], data: 0x%08x\r\n",
andrebharath 3:2e32d7974962 101 pMessage->code,pMessage->data);
andrebharath 3:2e32d7974962 102 outMessages.free(pMessage);
andrebharath 3:2e32d7974962 103 }
andrebharath 3:2e32d7974962 104 }
andrebharath 3:2e32d7974962 105
andrebharath 9:ecef1e8cbe3d 106
andrebharath 9:ecef1e8cbe3d 107
TrebleStick 14:66746291017c 108 //Global varible for the Bitcoin Key,maxspeed and rotations_pending
TrebleStick 12:1b2e2540e4e1 109 volatile uint64_t newKey = 0; //check initialise value? ****
TrebleStick 14:66746291017c 110 volatile float maxspeed = 0, rotations_pending = 0;
TrebleStick 14:66746291017c 111 //mutex variables
TrebleStick 14:66746291017c 112 Mutex newKey_mutex;
TrebleStick 14:66746291017c 113 Mutex maxspeed_mutex;
TrebleStick 14:66746291017c 114 Mutex rotations_pending_mutex;
andrebharath 9:ecef1e8cbe3d 115
andrebharath 9:ecef1e8cbe3d 116 //Instantiate a Queue to buffer incoming characters
andrebharath 9:ecef1e8cbe3d 117 Queue<void, 8> inCharQ;
andrebharath 9:ecef1e8cbe3d 118 //serial port ISR to receive each incoming byte and place into queue
andrebharath 9:ecef1e8cbe3d 119 void serialISR() {
andrebharath 9:ecef1e8cbe3d 120 uint8_t newChar = pc.getc();
andrebharath 9:ecef1e8cbe3d 121 inCharQ.put((void*)newChar);
andrebharath 9:ecef1e8cbe3d 122 }
andrebharath 9:ecef1e8cbe3d 123
andrebharath 9:ecef1e8cbe3d 124
andrebharath 9:ecef1e8cbe3d 125
andrebharath 9:ecef1e8cbe3d 126
andrebharath 9:ecef1e8cbe3d 127 Thread decodeT;
andrebharath 9:ecef1e8cbe3d 128
TrebleStick 14:66746291017c 129 void setNewCmd(char s[CHAR_ARR_SIZE])
TrebleStick 14:66746291017c 130 {
TrebleStick 14:66746291017c 131 uint64_t newKey_;
andrebharath 17:80159ace5ddf 132 uint32_t torque_;
TrebleStick 14:66746291017c 133 float maxspeed_, rotations_pending_;
TrebleStick 14:66746291017c 134 //R
TrebleStick 14:66746291017c 135 if (sscanf(s, "R%f", &rotations_pending_)) {
andrebharath 17:80159ace5ddf 136 rotations_pending_mutex.lock();
andrebharath 17:80159ace5ddf 137 rotations_pending = rotations_pending_;
andrebharath 17:80159ace5ddf 138 rotations_pending_mutex.unlock();
andrebharath 17:80159ace5ddf 139 putMessage(MSG_ROT_PEN, rotations_pending);
TrebleStick 14:66746291017c 140 //V
TrebleStick 14:66746291017c 141 } else if (sscanf(s, "V%f", &maxspeed_)) {
andrebharath 17:80159ace5ddf 142 maxspeed_mutex.lock();
andrebharath 17:80159ace5ddf 143 maxspeed = maxspeed_;
andrebharath 17:80159ace5ddf 144 maxspeed_mutex.unlock();
andrebharath 17:80159ace5ddf 145 putMessage(MSG_MAX_SPD, maxspeed);
TrebleStick 14:66746291017c 146 //K
TrebleStick 14:66746291017c 147 } else if (sscanf(s, "K%llx", &newKey_)) {
andrebharath 17:80159ace5ddf 148 newKey_mutex.lock();
andrebharath 17:80159ace5ddf 149 newKey = newKey_;
andrebharath 17:80159ace5ddf 150 newKey_mutex.unlock();
andrebharath 17:80159ace5ddf 151 putMessage(MSG_NEW_KEY, newKey);
andrebharath 17:80159ace5ddf 152 } else if (sscanf(s, "T%u", &torque_)) {
andrebharath 17:80159ace5ddf 153 torque = torque_;
andrebharath 17:80159ace5ddf 154 putMessage(MSG_TORQUE, torque);
TrebleStick 14:66746291017c 155 //ERROR
TrebleStick 14:66746291017c 156 } else
TrebleStick 14:66746291017c 157 putMessage(MSG_INP_ERR, 0x404);
TrebleStick 14:66746291017c 158 }
TrebleStick 12:1b2e2540e4e1 159
andrebharath 9:ecef1e8cbe3d 160
andrebharath 9:ecef1e8cbe3d 161
andrebharath 9:ecef1e8cbe3d 162 void decodeFn() {
andrebharath 9:ecef1e8cbe3d 163 pc.attach(&serialISR);
andrebharath 9:ecef1e8cbe3d 164 char charSeq[CHAR_ARR_SIZE] = "";
andrebharath 9:ecef1e8cbe3d 165 uint8_t bufPos = 0;
andrebharath 9:ecef1e8cbe3d 166 while(1) {
TrebleStick 12:1b2e2540e4e1 167
andrebharath 9:ecef1e8cbe3d 168 if(bufPos >= CHAR_ARR_SIZE) {
andrebharath 9:ecef1e8cbe3d 169 putMessage(MSG_OVERFLOW, bufPos);
TrebleStick 12:1b2e2540e4e1 170 bufPos = 0;
andrebharath 9:ecef1e8cbe3d 171 }
TrebleStick 13:ecccfc611025 172 else{
TrebleStick 12:1b2e2540e4e1 173
TrebleStick 13:ecccfc611025 174 osEvent newEvent = inCharQ.get();
TrebleStick 13:ecccfc611025 175 uint8_t newChar = (uint8_t)newEvent.value.p;
TrebleStick 12:1b2e2540e4e1 176
TrebleStick 13:ecccfc611025 177 if(newChar == '\r' || newChar == '\n') {
TrebleStick 13:ecccfc611025 178 charSeq[bufPos] = '\0';
TrebleStick 13:ecccfc611025 179 bufPos = 0;
TrebleStick 13:ecccfc611025 180 setNewCmd(charSeq);
TrebleStick 13:ecccfc611025 181 }
TrebleStick 13:ecccfc611025 182 else {
TrebleStick 13:ecccfc611025 183 charSeq[bufPos] = newChar;
TrebleStick 13:ecccfc611025 184 bufPos++;
TrebleStick 13:ecccfc611025 185 }
TrebleStick 12:1b2e2540e4e1 186 }
andrebharath 9:ecef1e8cbe3d 187 }
andrebharath 9:ecef1e8cbe3d 188 }
andrebharath 9:ecef1e8cbe3d 189
andrebharath 9:ecef1e8cbe3d 190
andrebharath 9:ecef1e8cbe3d 191
andrebharath 9:ecef1e8cbe3d 192
andrebharath 9:ecef1e8cbe3d 193
andrebharath 3:2e32d7974962 194 volatile uint16_t hashcount = 0;
TrebleStick 0:88c3d6c8a4eb 195
andrebharath 9:ecef1e8cbe3d 196 void do_hashcount() {
TrebleStick 15:bd303ab8a21f 197 //putMessage(MSG_HASHCOUNT, hashcount);
andrebharath 3:2e32d7974962 198 hashcount = 0;
andrebharath 3:2e32d7974962 199 }
andrebharath 9:ecef1e8cbe3d 200
andrebharath 9:ecef1e8cbe3d 201
TrebleStick 0:88c3d6c8a4eb 202 //Set a given drive state
andrebharath 17:80159ace5ddf 203 void motorOut(int8_t driveState, uint32_t t){
TrebleStick 12:1b2e2540e4e1 204
TrebleStick 0:88c3d6c8a4eb 205 //Lookup the output byte from the drive state.
TrebleStick 0:88c3d6c8a4eb 206 int8_t driveOut = driveTable[driveState & 0x07];
TrebleStick 12:1b2e2540e4e1 207
TrebleStick 0:88c3d6c8a4eb 208 //Turn off first
andrebharath 17:80159ace5ddf 209 if (~driveOut & 0x01) L1L.pulsewidth_us(0);
TrebleStick 0:88c3d6c8a4eb 210 if (~driveOut & 0x02) L1H = 1;
andrebharath 17:80159ace5ddf 211 if (~driveOut & 0x04) L2L.pulsewidth_us(0);
TrebleStick 0:88c3d6c8a4eb 212 if (~driveOut & 0x08) L2H = 1;
andrebharath 17:80159ace5ddf 213 if (~driveOut & 0x10) L3L.pulsewidth_us(0);
TrebleStick 0:88c3d6c8a4eb 214 if (~driveOut & 0x20) L3H = 1;
TrebleStick 12:1b2e2540e4e1 215
TrebleStick 0:88c3d6c8a4eb 216 //Then turn on
andrebharath 17:80159ace5ddf 217 if (driveOut & 0x01) L1L.pulsewidth_us(t);
TrebleStick 0:88c3d6c8a4eb 218 if (driveOut & 0x02) L1H = 0;
andrebharath 17:80159ace5ddf 219 if (driveOut & 0x04) L2L.pulsewidth_us(t);
TrebleStick 0:88c3d6c8a4eb 220 if (driveOut & 0x08) L2H = 0;
andrebharath 17:80159ace5ddf 221 if (driveOut & 0x10) L3L.pulsewidth_us(t);
TrebleStick 0:88c3d6c8a4eb 222 if (driveOut & 0x20) L3H = 0;
andrebharath 17:80159ace5ddf 223 }
TrebleStick 12:1b2e2540e4e1 224
andrebharath 9:ecef1e8cbe3d 225 //Convert photointerrupter inputs to a rotor state
andrebharath 9:ecef1e8cbe3d 226 inline int8_t readRotorState(){
TrebleStick 0:88c3d6c8a4eb 227 return stateMap[I1 + 2*I2 + 4*I3];
andrebharath 17:80159ace5ddf 228 }
andrebharath 9:ecef1e8cbe3d 229
TrebleStick 12:1b2e2540e4e1 230 //Basic synchronisation routine
andrebharath 9:ecef1e8cbe3d 231 int8_t motorHome() {
TrebleStick 0:88c3d6c8a4eb 232 //Put the motor in drive state 0 and wait for it to stabilise
andrebharath 17:80159ace5ddf 233 motorOut(0, MAX_PWM_PERIOD);
andrebharath 3:2e32d7974962 234 wait(2.0);
TrebleStick 12:1b2e2540e4e1 235
TrebleStick 0:88c3d6c8a4eb 236 //Get the rotor state
TrebleStick 0:88c3d6c8a4eb 237 return readRotorState();
TrebleStick 0:88c3d6c8a4eb 238 }
andrebharath 3:2e32d7974962 239
andrebharath 3:2e32d7974962 240 void photointerrupter_isr()
andrebharath 3:2e32d7974962 241 {
andrebharath 3:2e32d7974962 242 int8_t intState = readRotorState();
andrebharath 17:80159ace5ddf 243 motorOut((intState-orState+lead+6)%6, torque); //+6 to make sure the remainder is positive
andrebharath 3:2e32d7974962 244 }
andrebharath 9:ecef1e8cbe3d 245
TrebleStick 12:1b2e2540e4e1 246
TrebleStick 0:88c3d6c8a4eb 247 //Main
andrebharath 9:ecef1e8cbe3d 248 int main() {
TrebleStick 12:1b2e2540e4e1 249
andrebharath 9:ecef1e8cbe3d 250 putMessage(MSG_RESET, 0);
andrebharath 9:ecef1e8cbe3d 251
TrebleStick 12:1b2e2540e4e1 252
andrebharath 9:ecef1e8cbe3d 253 commOutT.start(&commOutFn);
TrebleStick 12:1b2e2540e4e1 254
TrebleStick 12:1b2e2540e4e1 255 decodeT.start(&decodeFn);
TrebleStick 12:1b2e2540e4e1 256
andrebharath 9:ecef1e8cbe3d 257 // pc.printf("Hello\n\r");
TrebleStick 12:1b2e2540e4e1 258
andrebharath 9:ecef1e8cbe3d 259 //Run the motor synchronisation
andrebharath 9:ecef1e8cbe3d 260 orState = motorHome();
andrebharath 9:ecef1e8cbe3d 261 // pc.printf("Rotor origin: %x\n\r",orState);
andrebharath 9:ecef1e8cbe3d 262 //orState is subtracted from future rotor state inputs to align rotor and motor states
TrebleStick 12:1b2e2540e4e1 263
andrebharath 3:2e32d7974962 264 I1.rise(&photointerrupter_isr);
andrebharath 3:2e32d7974962 265 I2.rise(&photointerrupter_isr);
andrebharath 3:2e32d7974962 266 I3.rise(&photointerrupter_isr);
TrebleStick 12:1b2e2540e4e1 267
andrebharath 3:2e32d7974962 268 I1.fall(&photointerrupter_isr);
andrebharath 3:2e32d7974962 269 I2.fall(&photointerrupter_isr);
andrebharath 3:2e32d7974962 270 I3.fall(&photointerrupter_isr);
TrebleStick 12:1b2e2540e4e1 271
andrebharath 9:ecef1e8cbe3d 272 //Calling the ISR once starts the motor movement
andrebharath 9:ecef1e8cbe3d 273 photointerrupter_isr();
andrebharath 17:80159ace5ddf 274
andrebharath 17:80159ace5ddf 275
TrebleStick 12:1b2e2540e4e1 276
andrebharath 9:ecef1e8cbe3d 277 SHA256 sha256;
TrebleStick 12:1b2e2540e4e1 278
andrebharath 3:2e32d7974962 279 uint8_t sequence[] = {0x45,0x6D,0x62,0x65,0x64,0x64,0x65,0x64,
andrebharath 3:2e32d7974962 280 0x20,0x53,0x79,0x73,0x74,0x65,0x6D,0x73,
andrebharath 3:2e32d7974962 281 0x20,0x61,0x72,0x65,0x20,0x66,0x75,0x6E,
andrebharath 3:2e32d7974962 282 0x20,0x61,0x6E,0x64,0x20,0x64,0x6F,0x20,
andrebharath 3:2e32d7974962 283 0x61,0x77,0x65,0x73,0x6F,0x6D,0x65,0x20,
andrebharath 3:2e32d7974962 284 0x74,0x68,0x69,0x6E,0x67,0x73,0x21,0x20,
andrebharath 3:2e32d7974962 285 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
andrebharath 3:2e32d7974962 286 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
andrebharath 3:2e32d7974962 287 uint64_t* key = (uint64_t*)((int)sequence + 48);
andrebharath 3:2e32d7974962 288 uint64_t* nonce = (uint64_t*)((int)sequence + 56);
andrebharath 3:2e32d7974962 289 uint8_t hash[32];
TrebleStick 12:1b2e2540e4e1 290
andrebharath 9:ecef1e8cbe3d 291 Ticker hashcounter;
andrebharath 9:ecef1e8cbe3d 292 hashcounter.attach(&do_hashcount, 1.0);
TrebleStick 12:1b2e2540e4e1 293
TrebleStick 0:88c3d6c8a4eb 294 //Poll the rotor state and set the motor outputs accordingly to spin the motor
TrebleStick 0:88c3d6c8a4eb 295 while (1) {
TrebleStick 12:1b2e2540e4e1 296
andrebharath 9:ecef1e8cbe3d 297 *key = newKey;
TrebleStick 12:1b2e2540e4e1 298
TrebleStick 14:66746291017c 299
TrebleStick 14:66746291017c 300
TrebleStick 12:1b2e2540e4e1 301
andrebharath 9:ecef1e8cbe3d 302 sha256.computeHash(hash, sequence, 64);
TrebleStick 12:1b2e2540e4e1 303
andrebharath 3:2e32d7974962 304 if (hash[0] == 0 && hash[1] == 0) {
TrebleStick 15:bd303ab8a21f 305 //putMessage(MSG_NONCE_OK, *nonce);
andrebharath 3:2e32d7974962 306 }
andrebharath 3:2e32d7974962 307
andrebharath 3:2e32d7974962 308 (*nonce)++;
andrebharath 3:2e32d7974962 309 hashcount++;
TrebleStick 0:88c3d6c8a4eb 310 }
TrebleStick 0:88c3d6c8a4eb 311 }
andrebharath 9:ecef1e8cbe3d 312
TrebleStick 12:1b2e2540e4e1 313
TrebleStick 12:1b2e2540e4e1 314 // K12345678\r
TrebleStick 12:1b2e2540e4e1 315 // K12345678