Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Adafruit_MCP23017.h>
- Adafruit_MCP23017 mcp_1;
- Adafruit_MCP23017 mcp_2;
- // modes
- enum MODE {OFF, TURN_LEFT, TURN_RIGHT, HAZARD_LIGHTS};
- MODE mode = OFF;
- const int LED_COUNT = 8;
- const boolean MCP_MODE_ONE_BYTE_AT_ONCE = false;
- int currentCount = 0;
- int state = 0;
- boolean first_mode_call = true;
- long lastMillis = 0;
- // blink delay
- const long blinkMs = 50;
- // hazard light delay
- const long hazardDeltaMs = 250;
- const int hazardCountMax = hazardDeltaMs / blinkMs;
- int counterHazard = 0;
- boolean stateHazardActive = false;
- #define MCP_LEFT 0
- #define MCP_RIGHT 1
- int inline get_bit_from_int(int val, int pos) {
- int mask = 1 << pos;
- int masked_val = val & mask;
- return masked_val >> pos;
- }
- /*
- * @param mcp_num set MCP left or right
- * @param high_byte flag to write upper 8 bit of 16bit
- * @param val byte to be written
- * @param pos define a single bit, if NULL full 8 bit will be written
- */
- void write_to_MCP(byte mcp_num, boolean high_byte, byte val, byte pos) {
- // select right MCP
- Adafruit_MCP23017* mcp;
- mcp_num == MCP_LEFT ? *mcp = mcp_1 : *mcp = mcp_2;
- // set high byte offset
- int bit_offset = 0;
- high_byte ? bit_offset = 8: bit_offset = 0;
- if (MCP_MODE_ONE_BYTE_AT_ONCE) {
- // fast version goes here
- // direct I2C access for pos == NULL case, maybe if version below is too slow
- } else {
- // slower version
- if(pos == NULL) {
- // write bit by bit
- for(int i = 0; i < 8; i++) {
- mcp->digitalWrite(i + bit_offset, get_bit_from_int(val, i));
- }
- } else {
- // only write the desired position (one access only)
- mcp->digitalWrite(pos + bit_offset, val);
- }
- }
- debug_output(val);
- }
- void debug_output(int val) {
- // debug output
- Serial.print("mode: ");
- Serial.print(mode);
- Serial.print(" val: ");
- Serial.print(val);
- Serial.println();
- }
- void turn_left() {
- turn_generic(MCP_RIGHT, MCP_LEFT);
- }
- void turn_right() {
- turn_generic(MCP_LEFT, MCP_RIGHT);
- }
- void turn_generic(byte mcp_inactive, byte mcp_active) {
- if (first_mode_call) {
- // turn unused leds off once
- write_to_MCP(mcp_inactive, false, 0x00, NULL);
- write_to_MCP(mcp_inactive, true, 0x00, NULL);
- // reset count state
- currentCount = 0;
- // clear flag
- first_mode_call = false;
- }
- // calc output bit vector and write to MCPs
- int val = pow(2, currentCount) - 1;
- // check for reset
- if(currentCount == 0) {
- // force a complete write
- write_to_MCP(mcp_active, false, (byte)val, NULL);
- write_to_MCP(mcp_active, true, (byte)val, NULL);
- } else {
- // also pass position of bit
- write_to_MCP(mcp_active, false, (byte)val, currentCount);
- write_to_MCP(mcp_active, true, (byte)val, currentCount);
- }
- // counter logic
- currentCount++;
- if (currentCount > LED_COUNT) {
- currentCount = 0;
- }
- }
- void hazard_lights() {
- if (first_mode_call) {
- first_mode_call = false;
- counterHazard = 0;
- // turn all leds on once
- set_all_leds(0xFF);
- stateHazardActive = true;
- }
- // check for toggle condition
- if (counterHazard > hazardCountMax) {
- if (stateHazardActive) {
- set_all_leds(0x00);
- stateHazardActive = false;
- } else {
- set_all_leds(0xFF);
- stateHazardActive = true;
- }
- // reset counter
- counterHazard = 0;
- }
- counterHazard++;
- }
- void set_all_leds(byte val) {
- write_to_MCP(MCP_LEFT, false, val, NULL);
- write_to_MCP(MCP_LEFT, true, val, NULL);
- write_to_MCP(MCP_RIGHT, false, val, NULL);
- write_to_MCP(MCP_RIGHT, true, val, NULL);
- }
- void setup() {
- // setup serial
- Serial.begin(9600);
- // setup MCPs
- mcp_1.begin(0); // Start MCP 1 on Hardware address 0x20
- mcp_2.begin(1); // Start MCP 2 on Hardware address 0x21
- // configure all outputs
- for(int i = 0; i < 16; i++) {
- mcp_1.pinMode(i, OUTPUT);
- mcp_2.pinMode(i, OUTPUT);
- mcp_1.digitalWrite(i, 0);
- mcp_2.digitalWrite(i, 0);
- }
- // hard code mode here
- mode = TURN_LEFT;
- //mode = TURN_RIGHT;
- //mode = HAZARD_LIGHTS;
- }
- void loop() {
- // main loop
- if (millis() - lastMillis > blinkMs) {
- lastMillis = millis();
- // check for mode
- if (mode == TURN_LEFT) {
- turn_left();
- } else if (mode == TURN_RIGHT) {
- turn_right();
- } else if (mode == HAZARD_LIGHTS) {
- hazard_lights();
- } else {
- // mode is off, do nothing
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement