From afa89c6f5c77cbeb42f0b1718c6bca4bf74b232a Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Tue, 10 Oct 2023 13:24:39 -0700 Subject: [PATCH 1/2] ArduinoCounter: version 2.0 adds option to invert output. Not fully tested yet. --- .../ArduinoCounter/ArduinoCounter.cpp | 71 +++++++- .../ArduinoCounter/ArduinoCounter.h | 1 + .../ArduinoCounter/ArduinoCounter.ino | 171 ++++++++++++------ 3 files changed, 181 insertions(+), 62 deletions(-) diff --git a/DeviceAdapters/ArduinoCounter/ArduinoCounter.cpp b/DeviceAdapters/ArduinoCounter/ArduinoCounter.cpp index 214515183..53ceb5f2a 100644 --- a/DeviceAdapters/ArduinoCounter/ArduinoCounter.cpp +++ b/DeviceAdapters/ArduinoCounter/ArduinoCounter.cpp @@ -7,7 +7,7 @@ // COPYRIGHT: Altos Labs, 2023, based on code copyright UCSF 2008 // LICENSE: LGPL // -// AUTHOR: Nico Stuurman, nstuurman@altoslabs.com, 7/13/2023 +// AUTHOR: Nico Stuurman, nstuurman@altoslabs.com, 7/13/2023, 10/10/2023 // #include "ArduinoCounter.h" @@ -25,10 +25,13 @@ const char* g_DeviceNameArduinoCounterCamera = "ArduinoCounterCamera"; // Global info about the state of the Arduino. -const double g_Min_MMVersion = 1.0; -const double g_Max_MMVersion = 1.1; +const double g_Min_MMVersion = 2.0; +const double g_Max_MMVersion = 2.0; const char* g_versionProp = "Version"; const char* g_Undefined = "Undefined"; +const char* g_Logic = "Output Logic"; +const char* g_Direct = "Direct"; +const char* g_Invert = "Invert"; @@ -64,7 +67,8 @@ MODULE_API void DeleteDevice(MM::Device* pDevice) ArduinoCounterCamera::ArduinoCounterCamera() : imageBuffer_(0), nrCamerasInUse_(0), - initialized_(false) + initialized_(false), + invert_(false) { InitializeDefaultErrorMessages(); @@ -167,6 +171,11 @@ int ArduinoCounterCamera::Initialize() sversion << version_; CreateProperty(g_versionProp, sversion.str().c_str(), MM::Float, true, pAct); + pAct = new CPropertyAction(this, &ArduinoCounterCamera::OnLogic); + CreateProperty(g_Logic, g_Direct, MM::String, false, pAct); + AddAllowedValue(g_Logic, g_Direct); + AddAllowedValue(g_Logic, g_Invert); + initialized_ = true; @@ -745,6 +754,60 @@ int ArduinoCounterCamera::OnPort(MM::PropertyBase* pProp, MM::ActionType pAct) return DEVICE_OK; } +int ArduinoCounterCamera::OnLogic(MM::PropertyBase* pProp, MM::ActionType pAct) +{ + int ret = DEVICE_OK; + unsigned char command[2]; + command[0] = 'p'; + std::string answer; + if (pAct == MM::BeforeGet) + { + command[1] = '?'; + ret = WriteToComPort(port_.c_str(), (const unsigned char*)command, 2); + if (ret != DEVICE_OK) + return ret; + ret = GetSerialAnswer(port_.c_str(), "\r\n", answer); + if (ret != DEVICE_OK) + return ret; + if (answer == g_Invert) + invert_ = true; + else if (answer == g_Direct) + invert_ = false; + else + return DEVICE_SERIAL_INVALID_RESPONSE; + } + else if (pAct == MM::AfterSet) + { + std::string cmd; + pProp->Get(cmd); + if (cmd == g_Invert) { + command[1] = 'i'; + ret = WriteToComPort(port_.c_str(), (const unsigned char*)command, 2); + if (ret != DEVICE_OK) + return ret; + ret = GetSerialAnswer(port_.c_str(), "\r\n", answer); + if (ret != DEVICE_OK) + return ret; + if (answer != g_Invert) + return DEVICE_SERIAL_INVALID_RESPONSE; + invert_ = true; + } + else if (cmd == g_Direct) { + command[1] = 'd'; + ret = WriteToComPort(port_.c_str(), (const unsigned char*)command, 2); + if (ret != DEVICE_OK) + return ret; + ret = GetSerialAnswer(port_.c_str(), "\r\n", answer); + if (ret != DEVICE_OK) + return ret; + if (answer != g_Direct) + return DEVICE_SERIAL_INVALID_RESPONSE; + invert_ = false; + } + } + return DEVICE_OK; +} + int ArduinoCounterCamera::OnVersion(MM::PropertyBase* pProp, MM::ActionType pAct) { if (pAct == MM::BeforeGet) diff --git a/DeviceAdapters/ArduinoCounter/ArduinoCounter.h b/DeviceAdapters/ArduinoCounter/ArduinoCounter.h index 9bd4d3ecf..41f05f022 100644 --- a/DeviceAdapters/ArduinoCounter/ArduinoCounter.h +++ b/DeviceAdapters/ArduinoCounter/ArduinoCounter.h @@ -136,6 +136,7 @@ class ArduinoCounterCamera : public CCameraBase std::string port_; double version_; bool portAvailable_; + bool invert_; }; diff --git a/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino b/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino index 2efb3f3bc..734980465 100644 --- a/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino +++ b/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino @@ -1,89 +1,144 @@ -unsigned int version_ = 1; +// Arduino firmware that counts input pulses, relays these to +// the output, but stops doing so after a specified +// amount of pulses has been received. +// Since version 2, also can invert the output. +// Communicates through serial, commands: +// gnnn - starts pulse counting. nnn should be an +// integer number (of any size) +// s - Stops counting, and reverts to transducing +// all input to the output +// i - Info: returns identification string +// pn - Sets/Reads the flag inverting the input polarity +// n=i Invert the input to the output +// n=d Do not invert the input to the output +// n=? report output polarity - // pin on which to receive the trigger (2 and 3 can be used with interrupts, although this code does not use interrupts) - const int inPin = 2; - const int outPin = 8; - - const unsigned long timeOut = 1000; +unsigned int version_ = 2; - unsigned int counter = 0; - unsigned int limit; - boolean counting = false; - boolean inputWas; +// pin on which to receive the trigger (2 and 3 can be used with interrupts, although this code does not use interrupts) +const int inPin = 2; + + +const int outPin = 8; + +const unsigned long timeOut = 1000; + +unsigned int counter = 0; +unsigned int limit; +boolean counting = false; +boolean inputWas; +boolean invert = false; void setup() { // put your setup code here, to run once: - Serial.begin(115200); + Serial.begin(115200); - - pinMode(inPin, INPUT); - pinMode(outPin, OUTPUT); + pinMode(inPin, INPUT); + pinMode(outPin, OUTPUT); - inputWas = digitalRead(inPin); - + inputWas = digitalRead(inPin); } void loop() { - while(true){ - // put your main code here, to run repeatedly: - - if (Serial.available() > 0) { - int inByte = Serial.read(); - switch (inByte) { - - // go (i.e. start) 'g' followed by max number of TTLs to pass - case 103: - if (waitForSerial(timeOut)) { - limit = Serial.parseInt(); - Serial.write("Starting with "); - Serial.println(limit, DEC); + while (true) { + // put your main code here, to run repeatedly: + + if (Serial.available() > 0) { + int inByte = Serial.read(); + switch (inByte) { + + // go (i.e. start) 'g' followed by max number of TTLs to pass + case 103: + if (waitForSerial(timeOut)) { + limit = Serial.parseInt(); + Serial.write("Starting with "); + Serial.println(limit, DEC); // set limit here - counting = true; - counter = 0; - inputWas = digitalRead(inPin); - break; - } + counting = true; + counter = 0; + inputWas = digitalRead(inPin); + break; + } // stop 's'; i.e. operate in passthrough mode case 115: counting = false; - Serial.println("Stopping"); + Serial.println("Stopping"); break; // get info 'i'; what version are you? case 105: - Serial.println("ArduinoCounter version 1.0"); - } - - - } - + Serial.println("ArduinoCounter version 2.0"); + break; + // Sets/gets output polarity + case 112: + if (waitForSerial(timeOut)) { + int command = Serial.read(); + switch (command) { + case 105: // "i" + invert = true; + Serial.println("Invert"); + break; + + case 100: // "d" + invert = false; + Serial.println("Direct"); + break; + + case 63: // "?" + if (invert) { + Serial.println("Invert"); + } else { + Serial.println("Direct"); + } + break; + } + } + } + } + } - if (counting) { + if (counting) { + if (invert) { + if (inputWas && !(PIND & B00000100)) { + counter++; + inputWas = LOW; + PORTB = 1; + } else if (!inputWas && (PIND & B00000100)) { + counter++; + inputWas = HIGH; + if (counter <= limit) { + PORTB = 0; + } + } + } else { // do not invert output if (inputWas && !(PIND & B00000100)) { - counter++; - inputWas = LOW; - if (counter <= limit) { - PORTB = 0; - } + counter++; + inputWas = LOW; + if (counter <= limit) { + PORTB = 0; + } } else if (!inputWas && (PIND & B00000100)) { - inputWas = HIGH; - PORTB = 1; + inputWas = HIGH; + PORTB = 1; + } + } + } else { // not counting + if (invert) { + PORTB = !(PIND & B00000100); + } else { + PORTB = (PIND & B00000100) >> 2; } - } else { - PORTB = (PIND & B00000100) >> 2; - } + } } -} -bool waitForSerial(unsigned long timeOut) -{ + bool waitForSerial(unsigned long timeOut) { unsigned long startTime = millis(); - while (Serial.available() == 0 && (millis() - startTime < timeOut) ) {} + while (Serial.available() == 0 && (millis() - startTime < timeOut)) {} if (Serial.available() > 0) - return true; + return true; return false; -} + } From 2599940ef2ba69e81ec6d84aa439cb2b010ecdd5 Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Tue, 10 Oct 2023 15:58:15 -0700 Subject: [PATCH 2/2] ArduinoCounter firmware: fix brackets. --- .../ArduinoCounter/ArduinoCounter.ino | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino b/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino index 734980465..5da132724 100644 --- a/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino +++ b/DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino @@ -99,34 +99,34 @@ void loop() { } } } - } - if (counting) { - if (invert) { - if (inputWas && !(PIND & B00000100)) { - counter++; - inputWas = LOW; - PORTB = 1; - } else if (!inputWas && (PIND & B00000100)) { - counter++; - inputWas = HIGH; - if (counter <= limit) { - PORTB = 0; + + if (counting) { + if (invert) { + if (inputWas && !(PIND & B00000100)) { + counter++; + inputWas = LOW; + PORTB = 1; + } else if (!inputWas && (PIND & B00000100)) { + counter++; + inputWas = HIGH; + if (counter <= limit) { + PORTB = 0; + } } - } - } else { // do not invert output - if (inputWas && !(PIND & B00000100)) { - counter++; - inputWas = LOW; - if (counter <= limit) { - PORTB = 0; + } else { // do not invert output + if (inputWas && !(PIND & B00000100)) { + counter++; + inputWas = LOW; + if (counter <= limit) { + PORTB = 0; + } + } else if (!inputWas && (PIND & B00000100)) { + inputWas = HIGH; + PORTB = 1; } - } else if (!inputWas && (PIND & B00000100)) { - inputWas = HIGH; - PORTB = 1; } - } - } else { // not counting + } else { // not counting if (invert) { PORTB = !(PIND & B00000100); } else { @@ -134,11 +134,12 @@ void loop() { } } } +} - bool waitForSerial(unsigned long timeOut) { - unsigned long startTime = millis(); - while (Serial.available() == 0 && (millis() - startTime < timeOut)) {} - if (Serial.available() > 0) - return true; - return false; - } +bool waitForSerial(unsigned long timeOut) { + unsigned long startTime = millis(); + while (Serial.available() == 0 && (millis() - startTime < timeOut)) {} + if (Serial.available() > 0) + return true; + return false; +}