Go Down

Topic: Pin declaration question PB1 vs Pin 9 (solved related to FastDHT22 library) (Read 215 times) previous topic - next topic

mauam

Hi,

I'm far newer to the forum than to Arduino and I usually find my answers without annoying other people with questions like this  :smiley-roll-sweat:
I nearly gave up in trying to understand this and I can't let that happen. So i reach out to you and hope, someone can explain me why I get this behaviour.

I'm currently working on a small weather station project -> AtTiny85 reporting DHT22 data through 433MHz transmitter to an UNO which itself has a DHT22 Sensor and additional 2x16 LCD to display both readings.
Details to be found here: diy-funk-wetterstation-mit-dht22-attiny85-und-radiohead


I got it working but something is puzzling me and I fail to get the AHA experience.


On the receiver side (UNO)
If I define the DHT_Pin like so: [#define DHT_PIN 9] I won't get any readings. However, if I use [#define DHT_PIN PB1] it works like a charm.
From AtTiny85 I'm used to "strange" pin names. But not on the UNO...

The strange thing about it is: The Pins for the receiver module and the LCD Module are defined with the pin number and they work fine this way.

On this Forum I found a hint regarding the file hardware\arduino\avr\variants\standard\pins_arduino.h but I don't see anything wrong with it. (pin 9 is only mentioned once as declaration for a digital pwm pin on row 35)

Any Ideas why I cant access the DHT Sensor through pin 9?



IDE v1.8.9, target board Arduino/Genuino UNO

Code: [Select]
// source https://git.cryhost.de/crycode/attiny85-radiohead-dht22-weather-sensor/snippets/19

#define SERVER_ADDRESS 0x01
#define RH_SPEED 2000
#define RH_RX_PIN 5
#define LED_PIN 13
#define DHT_PIN PB1 //pin 9

#define RH_BUF_LEN 9
uint8_t rh_buf[RH_BUF_LEN];

#define RH_ASK_MAX_MESSAGE_LEN RH_BUF_LEN

#include <RHDatagram.h>
#include <RH_ASK.h>

//LCD Stuff
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 6, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

#include "dht22.h"
dht22 dht;

RH_ASK driver(RH_SPEED, RH_RX_PIN);
RHDatagram manager(driver, SERVER_ADDRESS);

float t = 0;
float h = 0;
uint8_t bat_percent = 0;
uint8_t bat_raw = 0;

void setup() {
  lcd.begin(16, 2);

  Serial.begin(9600);
  if (!manager.init()) {
    Serial.println("init failed");
    lcd.print("init failed");
  } else {
    Serial.println("init done");
    lcd.print("init ok...");

    lcd.setCursor(0, 1);
    lcd.print("wait for input");
  }

  dht_init(&dht, DHT_PIN);
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  if (manager.available()) {
    uint8_t len = sizeof(rh_buf);
    uint8_t from;
    if (manager.recvfrom(rh_buf, &len, &from)) {
      lcd.clear();
      digitalWrite(LED_PIN, HIGH);
      //Serial.print("got message from : 0x");
      //Serial.println(from, HEX);
      switch (rh_buf[0]) {
        case 0x00:
          // start message
          Serial.println("0x00 start");
          break;
        case 0x01:
          // DHT data
          //Serial.println("0x01 DHT data");
          memcpy(&t, &rh_buf[1], 4);
          memcpy(&h, &rh_buf[5], 4);
          Serial.print(t);
          Serial.print("°C - ");
          Serial.print(h);
          Serial.println("%");
          String lcddata = "O: " + String(t, 1) + char(223) + "C, " + String(h, 1) + "%";
          lcd.setCursor(0, 0);
          lcd.print(lcddata);
          readInsideTemp();
          break;
        case 0x02:
          // battery data
          //Serial.println("0x02 battery data");
          bat_percent = rh_buf[1];
          bat_raw = rh_buf[2];
          Serial.print(bat_percent);
          Serial.print("% Batery - ADC: ");
          Serial.println(bat_raw);
          break;
        case 0xee:
          // error
          Serial.println("0xEE error");
          break;
        default:
          // should never happen
          break;
      }
      digitalWrite(LED_PIN, LOW);
    }
  }
}

void readInsideTemp() {
  float tin = 0;
  float hin = 0;
  String lcddata;
  if (dht_read_data(&dht, &tin, &hin) == 1) {
    lcddata = "I: " + String(tin, 1) + char(223) + "C, " + String(hin, 1) + "%";
  } else {
    lcddata = "I: DHT NOK!";
  }
  lcd.setCursor(0, 1);
  lcd.print(lcddata);
}


Solution:
The Problem is related to the used Fast dht22 library by Sergey Denisov aka LittleBuster https://github.com/LittleBuster/avr-dht22

The library is hardcoded to Port B which played a trick on me.
hence DHT_PIN 1 is equal to Port B Pin 1 which refers to arduino pin 9
2 -> PB2 -> arduino pin 10 etc.

jremington

Probably something specific to the DHT library. Post a link to the site from which you downloaded it.

pert

PB1 is a macro that defines the bit position of the PB1 pin in the PORTB register. It is defined like this:
Code: [Select]
#define PB1 1

So this code:
Code: [Select]
dht_init(&dht, DHT_PIN);
is identical to:
Code: [Select]
dht_init(&dht, 1);

It doesn't seem likely that would work for a DHT22 sensor connected to Arduino pin 9. However, I can't be sure what is going on because I don't know what library you're using for your DHT22.

Please post a link (using the chain links icon on the forum toolbar to make it clickable) to where you downloaded that library from. Or if you installed it using Library Manger (Sketch > Include Library > Manage Libraries in the Arduino IDE or Libraries > Library Manager in the Arduino Web Editor) then say so and state the full name of the library.

mauam

Thank you so far for the Comments.

The library can be found here: https://github.com/LittleBuster/avr-dht22


@pert,
According to the picture below, PB1 is bound to physical Pin 15, which correlates to IDE/Arduino Pin 9
The Sensor is attached to this Pin and works fine as long as I define it with PB1


septillion

The library can be found here: https://github.com/LittleBuster/avr-dht22
The answer lies in the total absence of the word "Arduino" in that library ;) Aka, it's made for "plain" AVR use. A "normal  Arduino" is AVR based so you can use that library. But the library has no notion at all of all the Arduino stuff like how the pins are defined. Hence it just uses the direct style.
Use fricking code tags!!!!
I want x => I would like x, I need help => I would like help, Need fast => Go and pay someone to do the job...

NEW Library to make fading leds a piece of cake
https://github.com/septillion-git/FadeLed

pert

#5
Aug 21, 2019, 11:01 am Last Edit: Aug 21, 2019, 11:02 am by pert Reason: Fix code tags markup
According to the picture below, PB1 is bound to physical Pin 15, which correlates to IDE/Arduino Pin 9
This is true, but it doesn't in any way change the fact that PB1 is the same as 1. That number doesn't provide enough information to control a pin at the low level port/bit register level because PB1 only defines the bit position in the register, but it doesn't define which register to use.

The only reason your code works is because for some odd reason the library is hardcoded to use port B and you happened to pick a pin that was on port B:
https://github.com/LittleBuster/avr-dht22/blob/master/dht22.h#L22-L24
Code: [Select]
/*
 * Sensor's port
 */
#define DDR_DHT DDRB
#define PORT_DHT PORTB
#define PIN_DHT PINB

Give it a try with PD2 for proof.

mauam

The answer lies in the total absence of the word "Arduino" in that library ;)
Haha I see! this explains a lot! And it also shows me that I don't really "understand" what I'm doing :( Well I'm working on that matter ;)
Direct style does not have to be wrong or bad I guess. But it adds an additional complexity layer on top of the rest.
Thank you for your analysis and time!


The only reason your code works is because for some odd reason the library is hardcoded to use port B and you happened to pick a pin that was on port B:
Exactly this odd thing was the reason I wrote. it somehow worked but I could not even half way explain why.

Meanwhile I ran into other issues with the project (RadioHead together with Networking seems to be tricky)

I'll go back one step tomorrow and define DHT_PIN as PD2 to prove your argument :)
Also thank you!

septillion

Direct style does not have to be wrong or bad I guess.
No it's not. Both have Pro's and Con's. Direct is faster butt via the Arduino HAL is easier. Only fact that the library locks it to PortB is a bit weird.

But it adds an additional complexity layer on top of the rest.
I would phrase that as "it doesn't remove a layer of complexity" ;)
Use fricking code tags!!!!
I want x => I would like x, I need help => I would like help, Need fast => Go and pay someone to do the job...

NEW Library to make fading leds a piece of cake
https://github.com/septillion-git/FadeLed

pert

The other benefit of using Arduino API IO functions and Arduino pin numbers is it makes your code portable to any board the Arduino IDE supports.

Only fact that the library locks it to PortB is a bit weird.
Yes. They could have allowed that to be configured via the library's API easily enough.

mauam

The other benefit of using Arduino API IO functions and Arduino pin numbers is it makes your code portable to any board the Arduino IDE supports.
Yes. They could have allowed that to be configured via the library's API easily enough.
I guess Sergei's goal creating the "Fast DHT22 lib" was to cut as much weight as possible. And what I think by now, it was probably ment for one purpose only... hence the not so flexible declaration.


No it's not. Both have Pro's and Con's. Direct is faster butt via the Arduino HAL is easier. Only fact that the library locks it to PortB is a bit weird.
I would phrase that as "it doesn't remove a layer of complexity" ;)
True that :-)

I went back to basics and tested different pin declarations.

Code: [Select]
#define DHT_PIN PD2 //PB1

#include "dht22.h"
dht22 dht;

float t, h;

void setup() {
  Serial.begin(9600);
  dht_init(&dht, DHT_PIN);
}

void loop() {
  delay(1000);
  if (dht_read_data(&dht, &t, &h) == 1) {
    Serial.println("We have " + String(t) + "°C and " + String(h)+"% RelH");
  } else {
    Serial.println("DHT not available!");
  }
}


When configured as PB1 I only get a reading on physical pin 15 / arduino pin 9, which makes kind of sense.
However if it's declared as BD2 like in the sketch above, the only pin giving me  a reading is physical 16 / arduino pin 10 which, regarding to the image posted earlier is weird.

However.... Since Sergei bound the whole thing to port B -> using "#define DHT_PIN 1" has the same effect as setting it to "PB1" or "PD1".
The same with "pin 2, PD2, PB2" which all point to arduino pin 10.


Give it a try with PD2 for proof.
Writing this, I think I finally understand your earlier post :-)

septillion

However if it's declared as BD2 like in the sketch above, the only pin giving me  a reading is physical 16 / arduino pin 10 which, regarding to the image posted earlier is weird.
Weird because of the library is fixed to port B. But PD2 only is a mask that corresponds to the bit in de port D registers. Which, for port registers, simply means bit 2 for all ports. So PB2 and PD2 are the same mask :D
Use fricking code tags!!!!
I want x => I would like x, I need help => I would like help, Need fast => Go and pay someone to do the job...

NEW Library to make fading leds a piece of cake
https://github.com/septillion-git/FadeLed

mauam

#11
Aug 23, 2019, 01:48 pm Last Edit: Aug 23, 2019, 03:35 pm by mauam
Weird because of the library is fixed to port B.
I always seem to end up on port B (ard pin 9&10 both belong to this port :-)

septillion

Yes, that's because that portB is hardcoded in that library. So you can only pick pins on portB, no matter s you use the mask from portB or portD. Literally PD2 == PB2 == 0b00000100
Use fricking code tags!!!!
I want x => I would like x, I need help => I would like help, Need fast => Go and pay someone to do the job...

NEW Library to make fading leds a piece of cake
https://github.com/septillion-git/FadeLed

mauam

Alright. I added some infos on the initial post. Hopefully someone else will stumble over this thread and learn from it as I did :-)

Many thanks for your help!

Go Up