Last active
May 31, 2019 01:53
-
-
Save Bouni/10188466 to your computer and use it in GitHub Desktop.
Some tests for an MDB project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// global state variable | |
unsigned int coinstate; | |
// structure for storing the coin changer info | |
struct COIN_INFO { | |
byte feature_level; | |
unsigned int country_code; | |
byte scaling_factor; | |
byte decimal_places; | |
byte type_routing; | |
byte type_credit[16]; | |
}; | |
// struct for storing the tube status | |
struct TUBE_STATUS { | |
unsigned int full_status; | |
byte status[16]; | |
}; | |
COIN_INFO coin_info = | |
{0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; | |
TUBE_STATUS tube_status = | |
{0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; | |
void setup() { | |
Serial.begin(9600); | |
Serial1.begin(9600, true); | |
coinstate = 0; | |
Serial.println("VMC stated."); | |
} | |
void loop() { | |
// run the statemachine | |
statemachine(); | |
// everytime we wait we can do funny stuff here in the meantime :-) | |
// but make sure it takes not longer then 100ms, because we have to poll the | |
// coin acceptor every 100ms at least! | |
do_funny_stuff(); | |
} | |
unsigned int calculate_checksum(unsigned int data[], unsigned int n) { | |
unsigned int checksum = 0x000; | |
// sum up all bytes except the last one (thats the checksum!) | |
for(int i=0; i < n-1; i++) { | |
checksum += data[i]; | |
} | |
// cut off the bits higher than 8 using a simple binary & | |
checksum &= 0x0FF; | |
// check the calculation against the checksum | |
return checksum; | |
} | |
bool validate_checksum(unsigned int data[], unsigned int n) { | |
unsigned int checksum = calculate_checksum(data, n); | |
// check the calculation against the checksum | |
return (checksum == data[n-1]); | |
} | |
void do_funny_stuff() { | |
} | |
// A simple statemachine for the coinchanger | |
void statemachine() { | |
unsigned int reply[40]; | |
unsigned int data[40]; | |
// This will print the coinstate and then wait 10ms to avoid the buffers to be flooded | |
Serial.print("State "); | |
Serial.println(coinstate, DEC); | |
delay(10); | |
switch(coinstate) { | |
// We have just powered up | |
case 0: | |
Serial1.write9bit(0x108); | |
Serial1.write9bit(0x008); | |
coinstate++; | |
break; | |
// we have already sent the reset command | |
case 1: | |
// wait for an answer | |
if(Serial1.available() < 1) { | |
return; | |
} | |
if(Serial1.read() == 0x100) { | |
// ACK received go ahead in the statemachine | |
coinstate++; | |
} else { | |
// No ACK received, start again from the beginning | |
coinstate = 0; | |
} | |
break; | |
// Poll the coin changer | |
case 2: | |
Serial1.write9bit(0x10B); | |
Serial1.write9bit(0x00B); | |
coinstate++; | |
break; | |
// Wait for the JUST RESET to be received | |
case 3: | |
// Check if the received byte is just an ACK | |
// read and discard it if so | |
if(Serial1.peek() == 0x100) { | |
Serial1.read(); | |
return; | |
} | |
// If the first byte is no ACK, wait for 2 bytes to be received | |
if(Serial1.available() < 2) { | |
return; | |
} | |
// read the 2 bytes and verify it is the JUST RESET | |
for(int i = 0; i < 2; i++) { | |
reply[i] = Serial1.read(); | |
} | |
if(reply[0] == 0x000 && reply[1] == 0x100) { | |
// JUST RESET received, send ACk and go ahead | |
Serial1.write9bit(0x100); | |
coinstate++; | |
} else { | |
// something else received send RET | |
Serial1.write9bit(0x0AA); | |
} | |
break; | |
// send the SETUP command | |
case 4: | |
Serial1.write9bit(0x109); | |
Serial1.write9bit(0x009); | |
coinstate++; | |
break; | |
// wait for the answer | |
case 5: | |
// Wait for 24 bytes to be received | |
if(Serial1.available() < 24) { | |
return; | |
} | |
// read the replied 23 databytes + checksum | |
for(int i = 0; i < 24; i++){ | |
reply[i] = Serial1.read(); | |
} | |
// validate the checksum | |
if(validate_checksum(reply, 24)) { | |
// checksum oki send ACK, go ahead | |
Serial1.write9bit(0x100); | |
coinstate++; | |
} else { | |
// checksum incorrect, send RET | |
Serial1.write9bit(0x0AA); | |
} | |
break; | |
// store device info | |
case 6: | |
coin_info.feature_level = reply[0]; | |
coin_info.country_code = (reply[1] << 8 | reply[2]); | |
coin_info.scaling_factor = reply[3]; | |
coin_info.decimal_places = reply[4]; | |
coin_info.type_routing = (reply[5] << 8 | reply[6]); | |
for(int i = 0; i < 16; i++) { | |
coin_info.type_credit[i] = reply[i+7]; | |
} | |
coinstate++; | |
break; | |
// send TUBE STATUS command | |
case 7: | |
Serial1.write9bit(0x10A); | |
Serial1.write9bit(0x00A); | |
coinstate++; | |
break; | |
// wait for the answer | |
case 8: | |
// Wait for 19 bytes to be received | |
if(Serial1.available() < 19) { | |
return; | |
} | |
// read the replied 18 databytes + checksum | |
for(int i = 0; i < 19; i++){ | |
reply[i] = Serial1.read(); | |
} | |
// validate the checksum | |
if(validate_checksum(reply, 19)) { | |
// checksum ok send ACK, go ahead | |
Serial1.write9bit(0x100); | |
coinstate++; | |
} else { | |
// checksum incorrect, send RET | |
Serial1.write9bit(0x0AA); | |
} | |
break; | |
// store tube status info | |
case 9: | |
tube_status.full_status = (reply[0] << 8 | reply[1]); | |
for(int i=0; i < 19; i++) { | |
tube_status.status[i] = reply[i+2]; | |
} | |
coinstate++; | |
break; | |
// send coin type command | |
case 10: | |
// prepare the data for the coin type command | |
data[0] = 0x10C; | |
data[1] = 0x00C; | |
data[2] = 0x0FF; | |
data[3] = 0x0FF; | |
data[4] = 0x0FF; | |
data[5] = 0x0FF; | |
// calculate the necessary checksum | |
data[6] = calculate_checksum(data, 6); | |
for(int i = 0; i < 7; i++) { | |
Serial1.write9bit(data[i]); | |
} | |
coinstate++; | |
break; | |
// wait for the ACK of the coin changer | |
case 11: | |
reply[0] = Serial1.read(); | |
if(reply[0] == 0x100) { | |
// ACK received go ahead | |
coinstate++; | |
} else { | |
// No ACK received, send the coin type command again | |
Serial.print("Error: expected ACK, received instead: "); | |
Serial.println(reply[0], HEX); | |
coinstate--; | |
} | |
break; | |
// Now we should be able to dispense a coin | |
case 12: | |
Serial.println("boot proccess completed :-)"); | |
coinstate++; | |
break; | |
// Lets poll the coin changer no forever | |
case 13: | |
Serial1.write9bit(0x10B); | |
Serial1.write9bit(0x00B); | |
coinstate++; | |
break; | |
case 14: | |
// Check if the received byte is just an ACK | |
// read and discard it if so | |
if(Serial1.peek() == 0x100) { | |
Serial1.read(); | |
return; | |
} | |
// If the first byte is no ACK, wait for 16 bytes to be received | |
if(Serial1.available() < 16) { | |
return; | |
} | |
for(int i = 0; i < 17; i++) { | |
reply[i] = Serial1.read(); | |
} | |
// validate the checksum | |
if(validate_checksum(reply, 17)) { | |
// checksum ok send ACK, go ahead | |
Serial1.write9bit(0x100); | |
coinstate++; | |
} else { | |
// checksum incorrect, send RET | |
Serial1.write9bit(0x0AA); | |
} | |
break; | |
// Lets write the reply to the console for testing purposes | |
case 15: | |
for(int i = 0; i < 17; i++) { | |
Serial.print("Byte "); | |
Serial.print(i, DEC); | |
Serial.print(" = "); | |
Serial.println(reply[i]); | |
} | |
delay(50); | |
coinstate = 13; | |
break; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*Power Up* | |
VMC: Reset 0x108 0x008 | |
Coin: Ack 0x100 | |
// Now poll as long as you get the Just Reset | |
// That can happen emdiately after the Reset, but also | |
// can take a few seconds with ACK answers in between | |
VMC: Poll 0x10B 0x00B | |
Coin: Ack 0x100 | |
VMC: Poll 0x10B 0x00B | |
Coin: Ack 0x100 | |
VMC: Poll 0x10B 0x00B | |
Coin: Ack 0x100 | |
VMC: Poll 0x10B 0x00B | |
Coin: Just Reset 0x000 0x100 | |
// Now get the Coin Mech setup information. See MDB Spec page 64 for details | |
// Store this infomation in a struct | |
VMC: Setup 0x109 0x009 | |
Coin: Answer [1 Byte] // Feature level | |
[2 Bytes] // Country / Currency Code | |
[1 Byte] // Coin Scaling factor | |
[1 Byte] // Decimal Places | |
[2 Bytes] // Coin Routing | |
[16 Bytes] // Coin Type Credit | |
[1 Byte] // Checksum | |
VMC: Ack 0x100 | |
VMC: Tube Status 010A 0x00A | |
Coin: Answer [2 Bytes] // Tube Full Status | |
[16 Bytes] // Tube Status | |
[1 Byte] // Checksum | |
VMC: Ack 0x100 | |
// Whenever you idle around, you need to send polls to the device to make sure they are alive | |
// But expect every time you poll that you get up to 16 Bytes of Status Data | |
VMC: Poll 0x10B 0x00B | |
Coin: Ack 0x100 | |
// Now enable the coin types for dispense (only need to be done once) | |
VMC: Coin Type 0x10C 0x00C | |
0x0FF 0x0FF // activate all coin types | |
0x0FF 0x0FF // activate all coin types for maual dispense | |
[1 Byte] // Checksum | |
Coin: Ack | |
// Now dispense a coin | |
// From here you can cycle and dispense as much coins as you wnat | |
VMC: Dispense 0x10D 0x00D | |
0x011 // 0b00110001 -> Bit 0 means Coin type 1, bit 4 and 5 means dispnse 3 coins | |
[1 Byte] // Checksum | |
Coin: Ack 0x100 | |
// If you poll after the Ack of the coin mech, you get the status of the dispense. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// connect Serial1 Rx to Serial2 Tx | |
// connect Serial2 Rx to Serial1 Tx | |
void setup() | |
{ | |
Serial.begin(9600); | |
Serial1.begin(9600,true); | |
Serial2.begin(9600,true); | |
Serial.println("Setup completed"); | |
} | |
void loop() | |
{ | |
unsigned int tmp; | |
Serial.println("sending 0x000 on Serial1"); | |
Serial1.write9bit(0x000); | |
Serial.println("wait for arrival on Serial2"); | |
while(!Serial2.available()) { | |
delay(1); | |
} | |
tmp = Serial2.read(); | |
Serial.println("received on Serial2:"); | |
Serial.println(tmp, HEX); | |
Serial.println("sending 0x100 on Serial1"); | |
Serial1.write9bit(0x100); | |
Serial.println("wait for arrival on Serial2"); | |
while(!Serial2.available()) { | |
delay(1); | |
} | |
tmp = Serial2.read(); | |
Serial.println("received on Serial2:"); | |
Serial.println(tmp, HEX); | |
Serial.println("sending 0x000 on Serial2"); | |
Serial2.write9bit(0x000); | |
Serial.println("wait for arrival on Serial1"); | |
while(!Serial1.available()) { | |
delay(1); | |
} | |
tmp = Serial1.read(); | |
Serial.println("received on Serial1:"); | |
Serial.println(tmp, HEX); | |
Serial.println("sending 0x100 on Serial2"); | |
Serial2.write9bit(0x100); | |
Serial.println("wait for arrival on Serial1"); | |
while(!Serial1.available()) { | |
delay(1); | |
} | |
tmp = Serial1.read(); | |
Serial.println("received on Serial1:"); | |
Serial.println(tmp, HEX); | |
} |
I'm trying to make a source code for VMC to communicate with the Coin Changers devices and also cashless devices.
So far I'm using the Flowcode Software, this can be used to program Pics and Arduinos with atmel chips.
So if you want some information please let me know.
Thanks
Omar Cangas
what is your definition for function Serial1.write9bit? it does not exist when i compile it
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Bouni, just to ask for what kind of device is this code for? is for Arduino?
Thanks
Omar Cangas