Arduino CBUS Library Instructions 1.0
User Manual:
Open the PDF directly: View PDF
.
Page Count: 7
| Download | |
| Open PDF In Browser | View PDF |
CBUS Library for Arduino Introduction This set of libraries implements a complete CBUS module using the Arduino environment. A minimum of additional code is required to create a fully-functional FLiM-compliant module. CBUS CBUS2515 CBUSLED CBUSswitch CBUSconfig - an abstract base class containing the commom methods an implementation of CBUS specifically for the MCP2515/25625 controller non-blocking LED management non-blocking pushbutton switch management event and node variable storage in on-chip or external EEPROM No additional code need be written to integrate with FCU or JMRI or to learn events. Features include: • • • • • • • • CBUS switch and FLiM/SLiM LEDs transition to and from FLiM/SLiM, tested with FCU and JMRI Node Manager event learning and storage, with configurable number of event variables node variable (NV) configuration and storage storage can use the on-chip 1K EEPROM or external I2C EEPROM up to 64K reset capability to return the module to an empty configuration a user-assignable function to be called when a learned event is received power-on reset capability to empty any stored events and NVs All four libraries a required although the LED and switch libraries can be used standalone in other projects if you find them useful. The download links are: CBUS CBUS2515 CBUSLED CBUSswitch CBUSconfig - https://github.com/obdevel/CBUS https://github.com/obdevel/CBUS2515 https://github.com/obdevel/CBUSLED https://github.com/obdevel/CBUSswitch https://github.com/obdevel/CBUSconfig You will also need to install the following two 3rd party libraries: ACAN2515 Streaming - https://github.com/pierremolinaro/acan2515 - https://github.com/janelia-arduino/Streaming For people who may have used other CAN bus libraries (e.g. MCP_CAN), note that the ACAN2515 library implements interrupt handling and configurable send/receive buffers, so there is no need to code this yourself. Hardware The minimum hardware requirement to create a CBUS module is: • an Arduino processor board, e.g. Uno, Nano, Mega, Pro Mini, etc • • • a CAN bus module based on the MCP2515 chip (available from multiple eBay sellers) two LEDs (green and yellow/amber) with 1K resistors a pushbutton switch As an alternative, I have designed a generic through-hole PCB containing all the above. It has no module-specific components, but all spare IO pins are brought out to headers. The design files are available on the MERG wiki at: https://www.merg.org.uk/merg_wiki/doku.php?id=projects:canxmas If using separate components, connect up as follows: Arduino Uno pin 5V GND 10 (SS) 12 (MISO) 11 (MOSI) 13 (SCK) 2 (INT0) Module pin Vcc GND CS SO SI SCK INT Connect the green LED with its current-limiting resistor between Arduino pin 4 and GND Connect the yellow LED with its current-limiting resistor between Arduino pin 5 and GND Connect the pushbutton switch between Arduino pin 6 and GND You may find a breadboard handy for the connections. Using the library The CBUS library includes a starter sketch in the example folder. This creates a complete but ‘empty’ module with no specific personality. Here is a commentary on the example code: 1. include the required libraries // 3rd party libraries #include// CBUS library header files #include #include #include #include #include // // // // // CAN controller and CBUS class pushbutton switch CBUS LEDs module configuration MERG CBUS constants // // // // CBUS object configuration object LED objects switch object // local header #include "defs.h" 2. create the CBUS objects CBUS2515 CBUS; CBUSConfig config; CBUSLED ledGrn, ledYlw; CBUSSwitch pb_switch; 3. create the module parameter variables and set the module’s name: // CBUS module parameters unsigned char params[21]; // module name, e.g. CANEMPTY J unsigned char mname[7] = { 'E', 'M', 'P', 'T', 'Y', ' ', ' ' }; 4. in the setup() function: (a) set the module’s event and NV storage configuration: // set config layout parameters config.EE_NVS_START = 10; config.EE_NUM_NVS = 10; config.EE_EVENTS_START = 50; config.EE_MAX_EVENTS = 64; config.EE_NUM_EVS = 1; config.EE_BYTES_PER_EVENT = (config.EE_NUM_EVS + 4); // initialise and load configuration config.setEEPROMtype(EEPROM_INTERNAL); config.begin(); (b) set the module’s parameters: // set module parameters params[0] = 20; params[1] = 0xa5; params[2] = VER_MIN; params[3] = MODULE_ID; params[4] = config.EE_MAX_EVENTS; params[5] = config.EE_NUM_EVS; params[6] = config.EE_NUM_NVS; params[7] = VER_MAJ; params[8] = 0x05; params[9] = 0x32; params[10] = PB_CAN; params[11] = 0x00; params[12] = 0x00; params[13] = 0x00; params[14] = 0x00; params[15] = '3'; params[16] = '2'; params[17] = '8'; params[18] = 'P'; params[19] = CPUM_ATMEL; params[20] = VER_BETA; // // // // // // // // // // // 0 1 2 3 4 5 6 7 8 9 10 num params manf = MERG, 165 code minor version module id, 99 = undefined num events num evs per event num NVs code major version flags = 5, FLiM, consumer processor id = 50 interface protocol = CAN, 1 // assign to CBUS CBUS.setParams(params); CBUS.setName(mname); (c) configure the pushbutton switch and check for power-on reset: // initialise CBUS switch pb_switch.setPin(SWITCH0, LOW); // module reset - if switch is depressed at startup and module is in SLiM mode pb_switch.run(); if (pb_switch.isPressed() && !config.FLiM) { Serial << F("> switch was pressed at startup in SLiM mode") << endl; config.resetModule(ledGrn, ledYlw, pb_switch); } (d) register the user-defined function to be called when a learned event is received: // register our CBUS event handler, to receive event messages of learned events CBUS.setEventHandler(eventhandler); (e) configure the LED pins and indicate the current module mode (FLiM or SLiM): // set LED and switch pins and assign to CBUS ledGrn.setPin(LED_GRN); ledYlw.setPin(LED_YLW); CBUS.setLEDs(ledGrn, ledYlw); CBUS.setSwitch(pb_switch); // set CBUS LEDs to indicate the current mode CBUS.indicateMode(config.FLiM); (f) configure the CAN bus parameters and start CBUS message processing: // configure and start CAN bus and CBUS message processing CBUS.setNumBuffers(4); CBUS.setPins(10, 2); CBUS.begin(); 4. implement a simple loop() function: void loop() { // /// do CBUS message, switch and LED processing // CBUS.process(); } 5. implement a simple user-defined function to handle received events (note that EVs and NVs number from one, not zero): void eventhandler(byte index, CANFrame *msg) { // as an example, display the opcode and first EV of this event Serial << F("> event handler: index = ") << index << F(", opcode = 0x") << _HEX(msg>data[0]) << endl; byte ev = 1; byte eeaddress = config.EE_EVENTS_START + (index * config.EE_BYTES_PER_EVENT) + 4 + (ev 1); Serial << F("> EV1 = ") << config.readEEPROM(eeaddress) << endl; return; } Header File The example sketch includes a module-specific header file (defs.h) which defines some local constants, as follows: #include // for definition of byte datatype // constants static const static const static const static const // // // // byte char byte byte VER_MAJ = 1; VER_MIN = 'a'; VER_BETA = 0; MODULE_ID = 99; code code code CBUS major version minor version beta sub-version module type static const byte LED_GRN = 4; static const byte LED_YLW = 5; // CBUS green SLiM LED pin // CBUS yellow FLiM LED pin static const byte SWITCH0 = 6; // CBUS push button switch pin Adding the module’s personality The foregoing implements a module that has no useful functionality. Consumer Modules The user-defined function is called whenever a message that matches a learned event is received; this is the entry point for implementing a Consumer module. It goes without saying that this function will not be called until the module has been taught at least one event. The following useful data is passed to this function when it is called: byte index; This is the index into the module’s event table. The Event Variables (EVs) can then be located. CANFrame *msg; A pointer to a CANFrame object containing the following: msg->id msg->len msg->data[0] msg->data[1] and [2] msg->data[3] and [4] // // // // // the the the the the CANID of the sending node number of data bytes in the frame’s payload opcode of the received message Node Number (NN) of the sending module Event Number (EN) of the received message Bytes 5-7 are additional data bytes that are send by some opcodes. See the CBUS Developers’ Guide for more information on opcodes. Producer Modules A Producer module will need to send CBUS messages when something of interest happens, e.g. a switch is pressed, a loco is detected, etc. It is up to you to define the following items for any CBUS messages you wish to send: • the opcode, depending on whether it is a simple on/off event (e.g. ACON/ACOF) or something more complex with additional data bytes (e.g. ACON3/ACOF3) • the Event Number (EN) This example shows how to send a simple ON event message with event number 1 and no additional data bytes: // create and initialise a message object CANFrame msg; memset(&msg, 0, sizeof(msg)); // populate the object’s parameters // the CANID msg.id = config.CANID; // the size of the data payload msg.len = 5; // the opcode msg.data[0] = OPC_ACON; // the module’s node number (NN) msg.data[1] = highByte(config.nodeNum); msg.data[2] = lowByte(config.nodeNum); // the event number (EN) msg.data[3] = 0; msg.data[4] = 1; // send the message bool sent_ok = CBUS.sendMessage(&msg); This function returns true if the message was successfully sent or false if not. Note that the NN and EN are both 16-bit integers and each occupy two bytes of the message. The Arduino macros highByte() and lowByte() return the appropriate (8-bit) byte from a 16-bit integer. See the CBUS Developers’ Guide for a full discussion of short and long events and the meaning of NN and EN. Module Reset The Arduino environment provides no easy way to program the microcontroller’s on-chip EEPROM. To ensure that the contents of the EEPROM are cleared and set to sensible defaults, the CBUSconfig library provides a simple method for resetting the module. This is shown in the example program included with the library. Hold down the pushbutton switch as you power-on the module. Then, as a safety precaution, press and hold the switch for a further 5 seconds. The module will then reset the EEPROM contents and reboot. The Node Number and CANID will both be set to zero. The module can only be reset whilst in SLiM mode (with the green LED illuminated). If, due to random EEPROM data, the module starts up in FLiM mode (with the yellow LED illuminated) or you want to reset the module at any time in the future, hold the switch down for 6 seconds to revert to SLiM mode. You can then proceed to reset the module. CBUS SLiM Mode The library does not currently support SLiM mode; that is, there is no provision for setting the node number or learning events by hardware switches. Therefore, you must use FCU or JMRI to configure your module in FLiM mode. This is in common with most newer MERG CBUS modules. Support for SLiM configuration and event learning may be added as a future enhancement if demand exists. Arduino Serial Port The library prints every received event to the module’s serial port (115200 baud, 8N1). This is useful for testing the bus connection or simply for monitoring the CBUS traffic. The library also prints copious debug information but by default this code is commented out. Selected lines can be uncommented to help with code debugging and development.
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.3 Linearized : No Page Count : 7 Title : Microsoft Word - Arduino CBUS Library Instructions 1.0.docx Producer : Mac OS X 10.13.6 Quartz PDFContext Creator : Word Create Date : 2019:05:22 19:47:16Z Modify Date : 2019:05:22 19:47:16ZEXIF Metadata provided by EXIF.tools