diff --git a/fhem/FHEM/20_FRM_IN.pm b/fhem/FHEM/20_FRM_IN.pm
index c9e7be8e3..f5750111e 100755
--- a/fhem/FHEM/20_FRM_IN.pm
+++ b/fhem/FHEM/20_FRM_IN.pm
@@ -32,7 +32,7 @@ FRM_IN_Initialize($)
$hash->{InitFn} = "FRM_IN_Init";
$hash->{UndefFn} = "FRM_IN_Undef";
- $hash->{AttrList} = "IODev count-mode:none,rising,falling,both count-threshold reset-on-threshold-reached:yes,no loglevel:0,1,2,3,4,5 $main::readingFnAttributes";
+ $hash->{AttrList} = "IODev count-mode:none,rising,falling,both count-threshold reset-on-threshold-reached:yes,no internal-pullup:on,off loglevel:0,1,2,3,4,5 $main::readingFnAttributes";
}
sub
@@ -41,8 +41,14 @@ FRM_IN_Init($$)
my ($hash,$args) = @_;
my $ret = FRM_Init_Pin_Client($hash,$args,PIN_INPUT);
return $ret if (defined $ret);
- my $firmata = $hash->{IODev}->{FirmataDevice};
- $firmata->observe_digital($hash->{PIN},\&FRM_IN_observer,$hash);
+ eval {
+ my $firmata = FRM_Client_FirmataDevice($hash);
+ $firmata->observe_digital($hash->{PIN},\&FRM_IN_observer,$hash);
+ if (defined (my $pullup = AttrVal($hash->{NAME},"internal-pullup",undef))) {
+ $firmata->digital_write($hash->{PIN},$pullup eq "on" ? 1 : 0);
+ }
+ };
+ return $@ if (defined $@);
if (! (defined AttrVal($hash->{NAME},"stateFormat",undef))) {
$main::attr{$hash->{NAME}}{"stateFormat"} = "reading";
}
@@ -162,6 +168,26 @@ FRM_IN_Attr($$$$) {
}
last;
};
+ $attribute eq "internal-pullup" and do {
+ eval {
+ my $hash = $main::defs{$name};
+ my $firmata = FRM_Client_FirmataDevice($hash);
+ $firmata->digital_write($hash->{PIN},$value eq "on" ? 1 : 0);
+ };
+ #ignore any errors here, the attribute-value will be applied next time FRM_IN_init() is called.
+ last;
+ };
+ }
+ } elsif ($command eq "del") {
+ ARGUMENT_HANDLER: {
+ $attribute eq "internal-pullup" and do {
+ eval {
+ my $hash = $main::defs{$name};
+ my $firmata = FRM_Client_FirmataDevice($hash);
+ $firmata->digital_write($hash->{PIN},0);
+ };
+ last;
+ };
}
}
}
@@ -222,7 +248,13 @@ FRM_IN_Undef($$)
edges (or 'both') are counted. Defaults to 'none'
count-threshold <number>
sets the theshold-value for the counter. Whenever 'count' reaches the 'count-threshold' 'alarm' is
- set to 'on' and count is reset to 0. Use 'set alarm off' to clear the alarm.
+ set to 'on'. Use 'set alarm off' to clear the alarm.
+ reset-on-threshold-reached yes|no
+ if set to 'yes' reset the counter to 0 when the threshold is reached (defaults to 'no').
+
+ internal-pullup on|off
+ allows to switch the internal pullup resistor of arduino to be en-/disabled. Defaults to off.
+
IODev
Specify which FRM to use. (Optional, only required if there is more
than one FRM-device defined.)
diff --git a/fhem/FHEM/lib/Device/Firmata/Platform.pm b/fhem/FHEM/lib/Device/Firmata/Platform.pm
index 82c2ee468..0f0e0c852 100644
--- a/fhem/FHEM/lib/Device/Firmata/Platform.pm
+++ b/fhem/FHEM/lib/Device/Firmata/Platform.pm
@@ -406,7 +406,7 @@ sub pin_mode {
# --------------------------------------------------
my ( $self, $pin, $mode ) = @_;
- return undef unless $self->is_supported_mode($pin,$mode);
+ die "unsupported mode '".$mode."' for pin '".$pin."'" unless $self->is_supported_mode($pin,$mode);
PIN_MODE_HANDLER: {
@@ -441,7 +441,7 @@ sub digital_write {
# --------------------------------------------------
my ( $self, $pin, $state ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_OUTPUT);
+ die "pin '".$pin."' is not configured for mode 'INPUT' or 'OUTPUT'" unless ($self->is_configured_mode($pin,PIN_OUTPUT) or $self->is_configured_mode($pin,PIN_INPUT));
my $port_number = $pin >> 3;
my $pin_offset = $pin % 8;
@@ -455,7 +455,7 @@ sub digital_write {
$port_state &= $pin_mask ^ 0xff;
}
$self->{ports}[$port_number] = $port_state;
- $self->{io}->data_write($self->{protocol}->message_prepare( DIGITAL_MESSAGE => $port_number, $port_state ));
+ $self->{io}->data_write($self->{protocol}->message_prepare( DIGITAL_MESSAGE => $port_number, $port_state & 0x7f, $port_state >> 7 ));
return 1;
}
@@ -470,7 +470,7 @@ sub digital_read {
# --------------------------------------------------
my ( $self, $pin ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_INPUT);
+ die "pin '".$pin."' is not configured for mode 'INPUT'" unless $self->is_configured_mode($pin,PIN_INPUT);
my $port_number = $pin >> 3;
my $pin_offset = $pin % 8;
my $pin_mask = 1 << $pin_offset;
@@ -489,7 +489,7 @@ sub analog_read {
# --------------------------------------------------
#
my ( $self, $pin ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_ANALOG);
+ die "pin '".$pin."' is not configured for mode 'ANALOG'" unless $self->is_configured_mode($pin,PIN_ANALOG);
return $self->{analog_pins}[$pin];
}
@@ -503,7 +503,7 @@ sub analog_write {
# Sets the PWM value on an arduino
#
my ( $self, $pin, $value ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_PWM);
+ die "pin '".$pin."' is not configured for mode 'PWM'" unless $self->is_configured_mode($pin,PIN_PWM);
# FIXME: 8 -> 7 bit translation should be done in the protocol module
my $byte_0 = $value & 0x7f;
@@ -584,7 +584,7 @@ sub servo_write {
# Sets the SERVO value on an arduino
#
my ( $self, $pin, $value ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_SERVO);
+ die "pin '".$pin."' is not configured for mode 'SERVO'" unless $self->is_configured_mode($pin,PIN_SERVO);
# FIXME: 8 -> 7 bit translation should be done in the protocol module
my $byte_0 = $value & 0x7f;
@@ -594,7 +594,7 @@ sub servo_write {
sub servo_config {
my ( $self, $pin, $args ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_SERVO);
+ die "pin '".$pin."' is not configured for mode 'SERVO'" unless $self->is_configured_mode($pin,PIN_SERVO);
return $self->{io}->data_write($self->{protocol}->packet_servo_config_request($pin,$args));
}
@@ -712,19 +712,19 @@ sub scheduler_query_task {
sub onewire_search {
my ( $self, $pin ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_ONEWIRE);
+ die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE);
return $self->{io}->data_write($self->{protocol}->packet_onewire_search_request( $pin ));
}
sub onewire_search_alarms {
my ( $self, $pin ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_ONEWIRE);
+ die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE);
return $self->{io}->data_write($self->{protocol}->packet_onewire_search_alarms_request( $pin ));
}
sub onewire_config {
my ( $self, $pin, $power ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_ONEWIRE);
+ die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE);
return $self->{io}->data_write($self->{protocol}->packet_onewire_config_request( $pin, $power ));
}
@@ -755,7 +755,7 @@ sub onewire_write {
sub onewire_command_series {
my ( $self, $pin, $args ) = @_;
- return undef unless $self->is_configured_mode($pin,PIN_ONEWIRE);
+ die "pin '".$pin."' is not configured for mode 'ONEWIRE'" unless $self->is_configured_mode($pin,PIN_ONEWIRE);
return $self->{io}->data_write($self->{protocol}->packet_onewire_request( $pin, $args ));
}
@@ -779,7 +779,7 @@ sub poll {
sub observe_digital {
my ( $self, $pin, $observer, $context ) = @_;
- return undef unless ($self->is_supported_mode($pin,PIN_INPUT));
+ die "unsupported mode 'INPUT' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_INPUT));
$self->{digital_observer}[$pin] = {
method => $observer,
context => $context,
@@ -789,7 +789,7 @@ sub observe_digital {
sub observe_analog {
my ( $self, $pin, $observer, $context ) = @_;
- return undef unless ($self->is_supported_mode($pin,PIN_ANALOG));
+ die "unsupported mode 'ANALOG' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_ANALOG));
$self->{analog_observer}[$pin] = {
method => $observer,
context => $context,
@@ -818,7 +818,7 @@ sub observe_i2c {
sub observe_onewire {
my ( $self, $pin, $observer, $context ) = @_;
- return undef unless ($self->is_supported_mode($pin,PIN_ONEWIRE));
+ die "unsupported mode 'ONEWIRE' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_ONEWIRE));
$self->{onewire_observer}[$pin] = {
method => $observer,
context => $context,
@@ -846,13 +846,13 @@ sub observe_string {
sub is_supported_mode {
my ($self,$pin,$mode) = @_;
- die "unsupported mode '".$mode."' for pin '".$pin."'" if (defined $self->{metadata}->{capabilities} and (!(defined $self->{metadata}->{capabilities}->{$pin}) or !(defined $self->{metadata}->{capabilities}->{$pin}->{$mode})));
+ return undef if (defined $self->{metadata}->{capabilities} and (!(defined $self->{metadata}->{capabilities}->{$pin}) or !(defined $self->{metadata}->{capabilities}->{$pin}->{$mode})));
return 1;
}
-
+
sub is_configured_mode {
my ($self,$pin,$mode) = @_;
- die "pin '".$pin."' is not configured for mode '".$mode."'" if (!defined $self->{pin_modes}->{$pin} or $self->{pin_modes}->{$pin} != $mode);
+ return undef if (!defined $self->{pin_modes}->{$pin} or $self->{pin_modes}->{$pin} != $mode);
return 1;
}