Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ability to set an individual digital pin value #102

Closed
SolidSoils opened this issue Nov 19, 2013 · 12 comments
Closed

add ability to set an individual digital pin value #102

SolidSoils opened this issue Nov 19, 2013 · 12 comments
Milestone

Comments

@SolidSoils
Copy link

Using analog messages (ANALOG 0xE0 and EXTENDED_ANALOG 0xF0-0x6F) we can control individual PWM and Servo pins. It is not possible to set the state of a digital output pin.

When a client system needs to set a digital output port, it must now first query the state of the port, mask the pin state and write the port's state back to the Arduino.

My proposal is to extend the analog messages to enable setting digital output pins. A 0 value would then map to LOW and any non-zero value would map to HIGH.

This would also be more consistent with the Pin State Query en Set Pin Mode commands.

I realize it's a bit odd writing a digital value using an analog message, but i.m.h.o. this is due to an inconsistency in the Firmata protocol itself: analog messages sent by the Arduino reflect the state of the true analog pins, where analog messages received by the Arduino are mapped to digital (PWM and Servo) pins.

@soundanalogous
Copy link
Member

I'd rather not further propagate inconsistencies (if anything I'd like to eliminate inconsistencies ... Frimata 3.0). Are you looking for something like this: setDitigalPin(pin, value) as an alternative to setDigitalPort(portNum, portData) or are you talking about something else here?

@SolidSoils
Copy link
Author

Exactly. I am developing a .NET library supporting serial communication with Arduino and supporting the Formata protocol. You can find it on Github: https://github.com/SolidSoils/Arduino

I actually designed a method (C#) public void SetPinValue(int pinNumber, ulong level). This method uses the analog message commands to control digital pins when in PWM or Servo mode. I hoped to extend this approach to digital pins in digital output mode.

A method named SetDigitalPin would be a good choice too. I will consider renaming my method :-)!

@soundanalogous
Copy link
Member

At least 2 other people have request this same functionality in the past 2 days. It should be possible to add. It seems to make sense for use cases where you have a firmata client that needs to connect by means other than serial (ethernet, bluetooth, etc) where you could have a client that connects and disconnects multiple times when the arduino never restarts (serial connection on the other hand automatically cause a hard reset of the board... this is an arduino HW thing). The only issue I can see is the case where the arduino restarts unexpectedly and the pin states are all reset. If you had then configured the pin states via your client application they would then be lost. However if the board restarts unexpectedly you'll know on the client side because you'll get a firmware version message on restart, this could indicate that on the client you need to reinitialize any pin states.

@soundanalogous
Copy link
Member

I've changed the name of this issue to better reflect the topic of the discussion.

@SolidSoils
Copy link
Author

Regarding your concerns about a hardware reset:
I think it's not the responsibility of a protocol to take the internal state of one of the parties involved into account. When it receives a command (i.e. telling to set a pin value) it's the Arduino system's sole responsibility to check if the operation is valid. If it is not, it can respond in either of two ways: silently ignore the command or return an error message/code.

Moreover, the client system commanding an Arduino can often be expected to only inquire the port states once (at startup) and maintain them in memory from there. In other words, the protocol itself does not (and should not) enforce the client to query a pin state immediately before setting it.

Therefore, I can see no good reasons to restrict the Firmata protocol at this point.

@soundanalogous
Copy link
Member

Do you have an idea for changes you'd like to see? This project moves slowly because very few people contribute to it (mostly just myself and Norbert at this point). It will evolve more quickly (and efficiently hopefully) if a couple more people with good ideas (and the appropriate SW skills) get involved :)

@SolidSoils
Copy link
Author

I'll be happy to contribute. However, I am not proficient at C++ and Arduino is pretty new to me. On the other hand years ago I did quite a lot of assembly language development and tinkered a bit with electronics. Do you think I should create a fork?

For the next 2.x version I do not see many changes needed. The protocol is well designed and covers most common requirements. I think implementation of a few enhancements (as already have been proposed) will suffice.

It would also be good to give some extra attention to the documentation. The wiki on SourceForge can be a bit more descriptive and the documentation on Arduino.cc is not in sync with the current Firmata version.

@soundanalogous
Copy link
Member

I'm open to adding something here for Firmata 2.4.0. I'm in favor of this version:

/* set digital pin
 * 0  START_SYSEX (0xF0)
 * 1  digital write pin command (TBD)
 * 2  pin-number
 * 3  high/low (0x01)
 * 4  END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
 */

One advantage here is that you could specify multiple pin values in a single message in case anyone wanted to set multiple digital pins that may be in different 'ports'. The implementation on the Arduino side would check the array length and iterate through the pins if there are multiple, setting each one.

/* set digital pin
 * 0  START_SYSEX (0xF0)
 * 1  digital write pin command (TBD)
 * 2  pin-number
 * 3  high/low (0x01)
 * 4  another pin
 * 5  high/low (0x01)
 * ...
 * n  END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
 */

Another option is if there is a 3 byte midi message that we are not currently using that would align with the following. It's been a while since I've looked at what midi messages were using vs what may be available so I'll have to find some time to look into this.

/* set digital pin
 * 0  some unused midi command
 * 1 pin number
 * 2 pin value
*/

@soundanalogous soundanalogous added this to the 2.4-beta2 milestone Aug 6, 2014
@soundanalogous
Copy link
Member

The ability to set individual pin values without sending a port value is now implemented in this branch: https://github.com/firmata/arduino/tree/set-pin-value. Will move to master once a few people have tested it. I've tested it successfully with BreakoutJS.

The protocol for this feature is here: https://github.com/firmata/protocol/blob/master/protocol.md#message-types. The command byte 0xF5 was used.

@rwaldron
Copy link
Contributor

I'll give it a spin this week

@soundanalogous
Copy link
Member

Moved to this PR: #211

@soundanalogous
Copy link
Member

This change is now in master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants