Gå til innhold
  • Bli medlem
Støtt hjemmeautomasjon.no!

Home Assistant og NAD C320BEE (dum) forsterker


frafall

Anbefalte innlegg

Etter å ha brutt ned mitt esp kontrollerte pepperkakehus var jeg i prosjekt vakuum etter jul, noe som utløste ideen om å koble min NAD C320BEE forsterker på nett for styring fra Home Assistant. Første tanken var en IR fra en Raspberry som står som streaming node i stereoanlegget men fikk lyst å grave litt dypere.

 

NAD har en IR in, IR ut og 12v trigger 3.5mm kontakt som jeg måtte utforske litt. Med litt googling fant jeg krets diagrammet for forsterkeren og det viser seg at det er relativt enkelt å koble seg på.

NAD-C320BEE-IR.png.3fa6f2c81e18c68fa9b6740a9f4b406e.png

 

  • IR in/ut er koblet via transistor drivere, forventer 5v men fungerer på 3.3v
  • IR ut gir ett rått modulert IR signal, dvs den videresender alle IR signaler selv om de ikke er NAD (SR5 for C320BEE)

 

Så, etter litt testing med en WeMos D1 mini (esp8266) ender jeg opp med en enkel kobling.

schematics.thumb.png.05fe4c929f522f170e216cc866881ca5.png

En enkel spenningsdeler på 12v for å detektere power status på forsterkeren og en pulldown på input from IR out (motstandene er basert på hva jeg hadde i skuffen..).

 

Dermed var det klart for å sette opp i ESPHome/Home Assistant:

  • IR bruker remote_receiver/remote_transmitter i ESPHome
  • Trigger 12v kobles på en binary_sensor
  • Kobler mot MQTT for direkte kontroll (utenom HA)
  • Definerer fjernkontroll funksjoner som button's i ESPHome, fjernkontrolleren er en tilfeldig jeg hadde liggende med NEC encoding, adresse 0x1000
  • Jeg liker at stereo anlegget virker selv om hjemme serveren er nede så jeg koder inn "on_nec" lokalt i remote_receiver for direkte kontroll.
  • Definerer en power switch (template switch) og mute for bruk i HA samt en template select for å velge forsterker input.

 

Styring av andre enheter

Siden jeg publiserer alle NEC IR koder til MQTT kan jeg fange opp andre fjernkontrollere og gjøre aksjoner i Home Assistant, f.eks styring av en media_player (MPD i mitt tilfelle).

automation:
  - alias: Hifi - play
    trigger:
      - platform: mqtt
        topic: ir/nec/0x1000
        encoding: utf-8
        payload: 40800
        value_template: "{{ value_json.command }}"

    condition: []

    action:
      - service: media_player.media_play
        data: {}
        target:
          entity_id: media_player.media_system
   
    mode: single

  - alias: Hifi - pause
    trigger:
      - platform: mqtt
        topic: ir/nec/0x1000
        encoding: utf-8
        payload: 40290
        value_template: "{{ value_json.command }}"

 

Notater om IR koder

Jeg hadde mistet NAD fjernkontrollen for mange år siden men jeg fant ut at den bruke SR5 i lirc som ser noe slikt ut:

begin remote

  name           NAD_SR5
  bits           16
  flags          SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header        9060  4418
  one           644  1600
  zero          644   478
  ptrail        644
  repeat        9059  2172
  pre_data_bits 16
  pre_data      0xE13E
  gap           107847
  toggle_bit    0


      begin codes
          KEY_POWER_ON             0xA45B
          KEY_POWER_OFF            0x13EC
          KEY_CD                   0xA15E
          KEY_TUNER                0xBB44
          KEY_AUX                  0xD926
          KEY_VIDEO                0x43BC
          KEY_DISC                 0x916E
          KEY_MUTE                 0x29D6
          KEY_VOLUMEUP             0x11EE
          KEY_VOLUMEDOWN           0x31CE
      end codes

end remote

 

Forsterkerens NEC IR addresse er gitt i pre_data som 0xE13E, ihht ESPHome NEC må denne bit-reverseres så forsterkerens adressen er 0x07C87.

Kommandoene gitt i lirc er som de sendes, dvs 8b inverted + 8b. Dette må bit reverseres for å få ESPHome NEC koden. 

Dermed kan vi konvertere lirc IR filer direkte til ESPHome NEC.

 

Eksempel:

Quote

Lirc Power on = 0xA45B

    0xA4 = 1010 0100 (inverted command)

    0x5B = 0101 1011 (command)

ESPHome NEC => 0010 0101 1101 1010 = 0x25DA

 

Videre

  • Jeg ser videre på muligheten for å få opp i2s (audio) for å gjøre forsterkeren til en streaming enhet, litt usikker på om lydkvaliteten blir ok, må kanskje skifte til en ESP32 for å kunne håndtere multirom streaming (Snapcast)
  • Prosjektet kan egentlig bygges inn i forsterkeren (garantien løp ut for noen år siden, ca 20?), den har 5v "alltid på" for sin innebygde IR kontroller, spørsmål om ev. støy fra ESP.

 

 

 

ESPHome YAML

esphome:
  name: "nad-c320bee"

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:


wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "nad-c320bee"
    password: "XXXXXXXXXX"

captive_portal:
    
# Should use hassio mqtt server
mqtt:
  topic_prefix: esp
  discovery: false
  broker: 192.168.0.99
  username: yyyyy
  password: xxxxxxxxxx
  id: mqtt_esphome

# Check 12v trigger 
binary_sensor:
  - platform: gpio
    name: "NAD Power State"
    id: nad_power_state
    pin:
      number: GPIO14  # D5
    device_class: power
    internal: false

    # Note power off/on resets the mute state
    on_state:
      - switch.template.publish:
          id: nad_mute
          state: OFF

# Direct from NAD IR-Output
remote_receiver:
  pin: 
    number: GPIO12 # D6
    inverted: False
  dump: all
  tolerance: 50%
  filter: 50us
  idle: 10ms

  # Publish all/most NEC parsed commands to MQTT
  on_nec:
    then:
      - if:
          condition:
            lambda: |-
              if(x.address != 0x1000) return true;

              switch(x.command) {

                // Volume down
                case 0xbf40:
                  id(nad_volumedown).press();
                  return false;

                // Volume up
                case 0xe01f:
                  id(nad_volumeup).press();
                  return false;

                // Volume mute
                case 0xe718:
                  id(nad_mute).toggle();
                  return false;

                // Power toggle
                case 0xff00:
                  id(nad_power).toggle();
                  return true;

                // Channel up
                case 0xef10: {
                  auto call = id(nad_input_source).make_call();
                  call.select_next(true);
                  call.perform();
                  return false;
                }

                // Channel down
                case 0xf00f: {
                  auto call = id(nad_input_source).make_call();
                  call.select_previous(true);
                  call.perform();
                  return false;
                }

                // Pass rest on
                default:
                  break;
              }

              return true;
          
          then:
            - mqtt.publish_json:
                topic: !lambda |-
                  static char topic[16];
                  sprintf(topic, "ir/nec/0x%x", x.address);
                  return topic;
                payload: !lambda |-
                  root["address"] = x.address;
                  root["command"] = x.command;

# Direct to NAD IR-Input
remote_transmitter:
  carrier_duty_percent: 50%
  pin: 
    number: GPIO13   # D7

switch:
  - platform: template
    name: "NAD Amplifier Power"
    id: nad_power
    icon: "mdi:audio-video"

    lambda: |-
      return id(nad_power_state).state;

    turn_on_action:
      - button.press: nad_cmd_poweron

    turn_off_action:
      - button.press: nad_cmd_poweroff

    optimistic: false
    assumed_state: false

  - platform: template
    name: "NAD Volume Mute"
    id: nad_mute
    icon: "mdi:audio-video"

    turn_on_action:
      - button.press: nad_cmd_mute

    turn_off_action:
      - button.press: nad_cmd_mute

    optimistic: true
    assumed_state: false


# XXX: Tape monitor (1) is not a toggle as rest...
#      it will co-exist with others

select:
  - platform: template
    name: "NAD Input Source"
    id: nad_input_source
    icon: "mdi:audio-video"

    options: 
      #- tape1
      - tape2
      - tuner
      - aux
      - video
      - cd
      - disc

    set_action: 
      - lambda: |-
          static const std::map<std::string, template_::TemplateButton *> input = {
            {"tape1", nad_cmd_tape1},
            {"tape2", nad_cmd_tape2},
            {"tuner", nad_cmd_tuner},
            {"aux",   nad_cmd_aux},
            {"video", nad_cmd_video},
            {"cd",    nad_cmd_cd},
            {"disc",  nad_cmd_disc},
          };

          // Delay needed to separate from earler (power on) commands
          delayMicroseconds(100000);

          if(auto it{ input.find(x) }; it != std::end(input)) {
            const auto&[key, value] {*it};
            value->press();
          } else {
            ESP_LOGD("main", "unknown source for amplifier input select [%s]", x.c_str());
          }

    restore_value: true
    optimistic: true

button:
  #
  # Address: 0x7C87 is 0111 1100 1000 0111
  # Reversed:          1110 0001 0011 1110 -> 0xE13E which is the address Lirc uses for SR5
  #
  # Command: 0x6B94 is 0100 1011 1001 0100 -> is inverted cmd + cmd
  #            6B => 0110 1011
  #            94 => 1001 0100
  # Reversed:           0010 1001 1101 0110 -> 0x29D6 which is the command Lirc uses for SR5
  #

  #
  # mosquitto_pub -h stuepi -u sysop -P xs2mf4ao -t esp/button/nad_mute/command -m 'PRESS'
  # 
  # Commands: Tuner, Aux, Video, CD, Disc (DD/9B/C2/85/89)
  #           Tape Monitor 1, Tape 2 (8D/91)
  #           Vol up/down, mute  (88/8C/94)
  #           Power on/off (25/C8)
  #

  - platform: template
    name: "NAD Select Tuner"
    id: nad_cmd_tuner
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x22DD
    internal: true

  - platform: template
    name: "NAD Select AUX"
    id: nad_cmd_aux
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x649b
    internal: true

  - platform: template
    name: "NAD Select VIDEO"
    id: nad_cmd_video
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x3dc2
    internal: true

  - platform: template
    name: "NAD Select CD"
    id: nad_cmd_cd
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x7a85
    internal: true

  - platform: template
    name: "NAD Select DISC"
    id: nad_cmd_disc
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x7689
    internal: true

  - platform: template
    name: "NAD Select Tape Monitor 1"
    id: nad_cmd_tape1
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x728d
    internal: true

  - platform: template
    name: "NAD Select Tape 2"
    id: nad_cmd_tape2
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x6e91
    internal: true

  - platform: template
    name: "NAD Volume up"
    id: nad_volumeup
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x7788

  - platform: template
    name: "NAD Volume down"
    id: nad_volumedown
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x738c

  - platform: template
    name: "NAD Mute"
    id: nad_cmd_mute
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x6B94
    internal: true

  - platform: template
    name: "NAD Power on"
    id: nad_cmd_poweron
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0xda25
    internal: true

  - platform: template
    name: "NAD Power off"
    id: nad_cmd_poweroff
    on_press:
      - remote_transmitter.transmit_nec:
          address: 0x7C87
          command: 0x37c8
    internal: true

 

Home assistant media player

media_player:

  #
  # Implementation of NAD amplifier
  #
  - platform: media_player_template
    media_players:
      nad_amplifier:
        friendly_name: NAD Amplifier
        device_class: receiver

        # value_template: "{{ states('switch.nad_amplifier_power') }}" <-- XXX: test this
        value_template: >
          {% if is_state("switch.nad_amplifier_power", "on") -%}
            on
          {%- else -%}
            off
          {%- endif %}

        #current_is_muted_template: "{{ states('switch.nad_volume_mute') }}" <-- XXX: test this
        current_is_muted_template: >
          {% if is_state("switch.nad_volume_mute", "on") -%}
            True
          {%- else -%}
            False
          {%- endif %}

        current_source_template: "{{ states('select.nad_input_source') }}"

        # Note tape1 is a "tape monitor" and coexists with the others
 
        inputs:
          tape2:
            service: select.select_option
            data:
              option: tape2
            target:
              entity_id: select.nad_input_source

          tuner:
            service: select.select_option
            data:
              option: tuner
            target:
              entity_id: select.nad_input_source

          aux:
            service: select.select_option
            data:
              option: aux
            target:
              entity_id: select.nad_input_source

          video:
            service: select.select_option
            data:
              option: video
            target:
              entity_id: select.nad_input_source

          cd:
            service: select.select_option
            data:
              option: cd
            target:
              entity_id: select.nad_input_source

          disc:
            service: select.select_option
            data:
              option: disc
            target:
              entity_id: select.nad_input_source

        turn_on:
          service: switch.turn_on
          target:
            entity_id: switch.nad_amplifier_power

        turn_off:
          service: switch.turn_off
          target:
            entity_id: switch.nad_amplifier_power

        mute:
          service: switch.toggle
          target:
            entity_id: switch.nad_volume_mute

        volume_up:
          service: button.press
          target:
            entity_id: button.nad_volume_up

        volume_down:
          service: button.press
          target:
            entity_id: button.nad_volume_down

 

  • Like 4
Lenke til kommentar
Del på andre sider

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

×
×
  • Opprett ny...

Viktig informasjon

Vi har plassert informasjonskapsler/cookies på din enhet for å gjøre denne siden bedre. Du kan justere dine innstillinger for informasjonskapsler, ellers vil vi anta at dette er ok for deg.