Go Down

Topic: TimerPWMCheatsheet (Read 1 time) previous topic - next topic

Ultrasonic2

i have a NANO and want to set the 0 timer to 62.5k so i have followed this guide
http://arduino.cc/playground/Main/TimerPWMCheatsheet

While changing it to 62.5k does work editing the wiring.c has no affect

i then thought i could just increase my delay by 64 times. This does make it appear to count at the correct rate however my DHT11 humidity sensor doesn't work.

Any thoughts guys 

robtillaart


you state several problems / solutions.

What is the real problem you want to solve?

The DHT11?  use a library that doesn't use delay to read it e.g. - http://arduino.cc/playground/Main/DHT11Lib -

(however it uses micros() that could be affected too by changing timer0 ...
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Ultrasonic2

Well i dont mid what the solution is to my problem but i want 62k and the  DHT11 working.

if it was a simple timing issue i would have though it would have worked when i multiplied the time by 64

MarkT



you state several problems / solutions.

What is the real problem you want to solve?

The DHT11?  use a library that doesn't use delay to read it e.g. - http://arduino.cc/playground/Main/DHT11Lib -

(however it uses micros() that could be affected too by changing timer0 ...


Will be affected - most of the time stuff (delay(), millis(), micros() - but not delayMicroseconds()) is totally relying on timer0.  Use a different timer if you don't want to upset things.
[ I won't respond to messages, use the forum please ]

Ultrasonic2

thanks for the suggestion . i

however that didn't help

Nick Gammon

Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Ultrasonic2

um thanks ? but i dont believe that has any relevance ?

Nick Gammon

Quote
i have a NANO and want to set the 0 timer to 62.5k so i have followed this guide
...

While changing it to 62.5k does work editing the wiring.c has no affect

i then thought i could just increase my delay by 64 times. This does make it appear to count at the correct rate however my DHT11 humidity sensor doesn't work.


Where is your code?

Are we supposed to guess what you have done, and why it doesn't work? See point 6 on the page I linked to.

Quote
and want to set the 0 timer to 62.5k


62.5k what? 62.5 kHz? 62.5 k milliseconds? microseconds? nanoseconds?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Ultrasonic2

This is just some simple code as example

now as mentioned before, everything works fine when set to the default settings but soon as as i change the timer 0 to 1 and do the below it the DHT11 doesn't work.

according to the link i posted i should change the wiring.c code to get it to count at the correct speed however changing this files does nothing. ( im not to worried about that as long as the DHT11 will work)

interestingly i've change the second timer to "1" and while it works after a while it starts giving incorrect information back 

Code: [Select]
#define DHT11_PIN 0      // ADC0 humididty
long fixtimer;
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args)  write(args);
#else
#define printByte(args)  print(args,BYTE);
#endif

uint8_t bell[8]  = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4};
uint8_t note[8]  = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0};
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
uint8_t duck[8]  = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0};
uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
 
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 20 chars and 4 line display

byte read_dht11_dat()// humididty
{
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++)
  {
    while(!(PINC & _BV(DHT11_PIN)));  // wait for 50us
    delayMicroseconds((30 * fixtimer));
    if(PINC & _BV(DHT11_PIN))
      result |=(1<<(7-i));
    while((PINC & _BV(DHT11_PIN)));  // wait '1' finish
    }
    return result;
}


void setup()
{
  TCCR0B = TCCR0B & 0b11111000 | 1;
 
  fixtimer = 64;
   DDRC |= _BV(DHT11_PIN); // Hum
  PORTC |= _BV(DHT11_PIN); //Hum
  Serial.begin(9600); //hum
  Serial.println("Ready"); //hum
 
//  Serial.begin(57600);
  lcd.init();                      // initialize the lcd
  lcd.backlight();
 
  lcd.createChar(0, bell);
  lcd.createChar(1, note);
  lcd.createChar(2, clock);
  lcd.createChar(3, heart);
  lcd.createChar(4, duck);
  lcd.createChar(5, check);
  lcd.createChar(6, cross);
  lcd.createChar(7, retarrow);
  lcd.home();
 
  lcd.setCursor(0, 0);
  for(int i = 0;i < 20; i++)  lcd.printByte(6);
  lcd.setCursor(0, 1);
  lcd.printByte(6);
  lcd.print("   Hello world    ");
  lcd.printByte(6);
  lcd.setCursor(0, 2);
  lcd.printByte(6);
  lcd.print("  i ");
  lcd.printByte(3);
  lcd.print(" Adele   !   ");
  lcd.printByte(6);
  lcd.setCursor(0, 3);
  for(int i = 0;i < 20; i++)  lcd.printByte(6);
//  lcd.clear();

}

void loop()
{
  byte dht11_dat[5];
  byte dht11_in;
  byte i;// start condition
// 1. pull-down i/o pin from 18ms
  PORTC &= ~_BV(DHT11_PIN);
  delay((18 * fixtimer));
  PORTC |= _BV(DHT11_PIN);
  delayMicroseconds((40 * fixtimer));
  DDRC &= ~_BV(DHT11_PIN);
  delayMicroseconds((40 * fixtimer));
 
  dht11_in = PINC & _BV(DHT11_PIN);
  if(dht11_in)
  {
    Serial.println("dht11 start condition 1 not met");
    return;
  }
  delayMicroseconds((80 * fixtimer));
  dht11_in = PINC & _BV(DHT11_PIN);
  if(!dht11_in)
  {
    Serial.println("dht11 start condition 2 not met");
    return;
  }
 
  delayMicroseconds((80 * fixtimer));// now ready for data reception
  for (i=0; i<5; i++)
    dht11_dat[i] = read_dht11_dat();
  DDRC |= _BV(DHT11_PIN);
  PORTC |= _BV(DHT11_PIN);
  byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];// check check_sum
  if(dht11_dat[4]!= dht11_check_sum)
  {
    Serial.println("DHT11 checksum error");
  }
  lcd.setCursor(0, 0);
  lcd.print(dht11_dat[0], DEC);
  lcd.setCursor(0, 2);
  lcd.print(dht11_dat[2], DEC);
  Serial.print("Current humdity = ");
  Serial.print(dht11_dat[0], DEC);
  Serial.print(".");
  Serial.print(dht11_dat[1], DEC);
  Serial.print("%  ");
  Serial.print("temperature = ");
  Serial.print(dht11_dat[2], DEC);
  Serial.print(".");
  Serial.print(dht11_dat[3], DEC);
  Serial.println("C  ");
  delay((2000 * fixtimer));
}



Nick Gammon


i have a NANO and want to set the 0 timer to 62.5k


Why do you want/need to to this?


Quote
While changing it to 62.5k does work editing the wiring.c has no affect


What editing?

Quote
Code: [Select]
 PORTC &= ~_BV(DHT11_PIN);


What is wrong with:

Code: [Select]
digitalWrite (A0, LOW);

Quote
Code: [Select]
 DDRC &= ~_BV(DHT11_PIN);


What is wrong with:

Code: [Select]
pinMode  (A0, INPUT);

This sort of stuff is hard to read, for no purpose:

Code: [Select]

 DDRC |= _BV(DHT11_PIN); // Hum
 PORTC |= _BV(DHT11_PIN); //Hum


Just say:

Code: [Select]
pinMode (SENSORPIN, OUTPUT);
digitalWrite (SENSORPIN, HIGH);


Why force people to reach for the datasheet, just to check you have the right bits and ports? Hopefully the sensor is plugged into A0 but you don't mention that.

The page you linked to mentions a library. Why don't you just use that?




By setting the prescaler to 1 you change the rate at which the Timer0 interrupt fires to be 64 times as often. Normally it fires every 1.024 mS and updates the counter used in millis() and micros(). Now it will fire every 1.024mS/64, that is 16 uS.

The interrupt service routine itself takes around 3 uS to fire, then it has to do stuff, and then another 3 uS to wrap up. Out of 16 uS it doesn't have much time. Amongst other things, I think that having these almost constant interrupts is going to throw out what looks like timing-dependent code.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Ultrasonic2

Right i'll start from the beginning myabe that will help. I have already created a dual channel Temperature controller.

The whole thing controls my Fans and TEC's which ultimately cools my computer. both sides of the TEC are water cooled ( hot and cold sides )

The first channel requires a target temp and the Arduino reads the zx-thermometer, which is measuring the TEC's HOT side water temp. The arduino will increase the duty cycle of the Fans to keep the water at the target temp.

The same is true for the cold side of the TEC however i have a dht11 which reads the ambient temp and humidity. The arduino then works out the dew point and sets the Target temp on the fly at 1c above dew point. The Arduino then changes the duty cycle of TEC's to keep the cold side water at the Target temp.

Now all of the above works just fine.

Because of efficiency gains at low pwm duty cycles when dealing with TEC's i want to convert the PWM to an analogue out put. To do this im using a Low pass filter. The TEC's pass 600watts. so the resistance of the resistors in the low pass filter is very low 0.135ohms. otherwise their is to much heat generated and to much voltage loss. because the arduino only switch at 1khz this means i have to have very large capacitance to reduce the ripple. approximately 164,000uf which of coarse is very large and expensive.

If i was able to run the arduino at 62.5khz it would then require 1/62 the amount of capacitance for the same ripple. which is what im trying to achieve. 

http://arduino.cc/playground/Main/TimerPWMCheatsheet

Now according to this post i can run the Arduino at 62.5khz  by adding this line to the start up
TCCR0B = TCCR0B & 0b11111000 | 1;

As far as i can tell making the above does increase it's frequency. However as the link says the arduino now counts to fast and the DHT no longer works.

According to the link you can fix the incorrect timing by changing this " #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(PRESCALE_FACTOR* 256))" line in this file "hardware\arduino\cores\arduino\wiring.c"

However this is not the case changing the wiring.c has no affect on how fast the Arduino seems to count.

Now i thought to my self this is no big deal i can just take the stock times and multiply them ( fixtimer in my code) by 64 to get back to the correct actual time. However this also does not work.

Now since changing timer 0 affects the arduinos timings as part of my testing i thought i could leave timer 0 at the stock timings and change timer 2. Now this wouldn't give me 62khz it would give me 31khz but that's still 32 times faster than the 1khz i have now. While running timer 2 at 1 the DHT11 works fine for a while but about 10 minutes later it starts giving incorrect numbers.

What does work is 4khz on timer 2 but no faster than that. 

Now the Code i posted clearly isn't my full project as part of my testing i stripped it back to the basics.

The code i posted i wrote NONE of it. When i bought the LCD and DHT from robotshop.com they came with code which i copied and pasted into my project.

So your comments on the code is actually a comment on code i didn't write and have NO idea why it is the way it is. Soo i have no idea what's wrong with it. especially since it all works with the stock timers 
         
Thanks for your valuable time

Nick Gammon

OK, well there are three timers. You might be better off doing analogWrite to one that is not on Timer 0. Then all those problems go away.

Only D5 and D6 are on Timer0.

Quote
Now since changing timer 0 affects the arduinos timings as part of my testing i thought i could leave timer 0 at the stock timings and change timer 2. Now this wouldn't give me 62khz it would give me 31khz but that's still 32 times faster than the 1khz i have now.


Ah, why?

Quote
While running timer 2 at 1 the DHT11 works fine for a while but about 10 minutes later it starts giving incorrect numbers.


Well, why is that? What incorrect numbers?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Ultrasonic2

"Ah, why?"
why what?

"Well, why is that? What incorrect numbers?"
it stops producing the correct humidity number

Nick Gammon

I'm not really interested in playing 20 questions with you, maybe someone else can help better.

You said:

Quote
Now since changing timer 0 affects the arduinos timings as part of my testing i thought i could leave timer 0 at the stock timings and change timer 2. Now this wouldn't give me 62khz it would give me 31khz but that's still 32 times faster than the 1khz i have now.


I said why? (Why does it not give 62 kHz?)

You reply:

Quote
why what?





Then you say:

Quote
i could leave timer 0 at the stock timings and change timer 2


Well, show this code, the code that does not give you 62 KHz.




You say:

Quote
it starts giving incorrect numbers


I say:

Quote
What incorrect numbers?


You reply:

Quote
it stops producing the correct humidity number


Yes, I know the incorrect number is not the correct number.

You need to put in debugging prints. You need to show your code, not just say "I tried X and it didn't work". If the numbers are incorrect you need to show the incorrect number (copy and paste) and what you think the correct numbers are, and why.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up