Sari la conținut
ELFORUM - Forumul electronistilor

Termometru cu DS18B20 si Digiti LED


GeoMar

Postări Recomandate

Am reusit o afisare satisfacatoare a temperaturii citita de DS, in defavoarea stralucirii afisajului. sper ca aceasta deficienta sa o pot corecta prin alimentarea digitilor prin tranzistori, nu direct din pinii Arduino.
Momentan asa arata codul folosit, nu stiu cat de bun/corect este, l-am creeat asa cum m-am priceput eu, ca un incepator:

 

//
// Sample of using Async reading of Dallas Temperature Sensors
// 
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SevenSeg.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

DeviceAddress tempDeviceAddress;


SevenSeg disp (8, 10, 6, 4, 3, 9, 7);
const int numOfDigits = 4;
int digitPins [ numOfDigits ] = { A2, A3, A4, A5};

int  resolution = 9;
unsigned long lastTempRequest = 0;
int  delayInMillis = 0;
float temperature = 0.0;
int  idle = 0;
//
// SETUP
//
void setup(void)
{

  disp . setDigitPins ( numOfDigits , digitPins );
  disp . setDPPin (5) ;
  disp.setRefreshRate(6000);

  sensors.begin();
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(tempDeviceAddress, resolution);
  
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  delayInMillis = 750 / (1 << (9 - resolution)); 
  lastTempRequest = millis(); 
     
  
}

void loop(void)
{ 
  
  if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
  {
     sensors.requestTemperatures();
     temperature = sensors.getTempCByIndex(0);
     disp. write ((temperature), 1);
     disp. setRefreshRate(6000);
  } 
}

 

 

Asa arata acum afisarea temperaturii citita de la DS18B20 pe afisajul LED cu 3 digiti.
In realitate acel licarit/flicar nu mai este sesizabil/suparator cum era inainte.

 

 

 

 

Vreau acum sa testez inserarea mai multor senzori DS (eventual identificarea lor automata) si afisarea lor ciclic, ca in clipul postat de mine cateva posturi mai sus.
Sper sa si reusesc.:rade:

 

Link spre comentariu
  • Răspunsuri 45
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Nu ar merge un alt doilea microcontroller slave ( ceva foarte ieftin ) care sa citeasca datele de la senzor si sa le puna in memoria RAM ?   Astfel procesorul principal doar citeste informatia de acolo ( o data pe secunda sa zicem ). Daca se intampla sa fie "ocupat" procesorul slave doar se face abort si se afiseaza temperatura anterioara. Asa nu va mai exista nici o palpaire.

Link spre comentariu

Initial n-am verificat daca libraria folosita suporta intreruperi, mai tarziu am vazut ca pentru  pentru ATmega 168 si 328 sunt suportate intreruperile generat de timerul 0,1 si 2. 
Am modificat putin codul din prima postare astfel incat sa se foloseasca, pentru multiplexare, intreruperea generata de timer 2.
Pe display la fiecare secunda este incrementat un contor incepand de la valoarea 1000.  
Verificati daca mai aveti acea palpaire.
 

#include <SevenSeg.h>
//#include <OneWire.h>
//#include <DallasTemperature.h>

SevenSeg disp (8, 10, 6, 4, 3, 9, 7);
const int numOfDigits = 4;
int digitPins [ numOfDigits ] = { A2, A3, A4, A5};

//#define ONE_WIRE_BUS 2
//OneWire oneWire(ONE_WIRE_BUS);
//DallasTemperature sensors(&oneWire);

void setup() {
  disp . setDigitPins ( numOfDigits , digitPins );
  disp . setDPPin (5) ;
 // sensors.begin();
  disp.setDutyCycle(100);
  disp.setRefreshRate(100);
  disp . setTimer (2) ;
  disp . startTimer () ;
}

void loop() {
   for ( int i=1000;i <=9999; i ++) {
 disp . write (i);
 delay (1000) ;  
   }
}
ISR ( TIMER2_COMPA_vect ){
    disp . interruptAction () ;
}

 

Link spre comentariu

Multumesc pentru implicare.
Maine seara dupa servici testez codul postat si revin cu informatii

Dupa cate imi amintesc eu, am testat si ceva afisari cu aceste intreruperi, tot apare fliker.    Cred ca este vorba de citirea DS-ului care baga intarzieri si apare acel fliker.
La testarea cu un counter afisat pe digiti, nu se sesizeaza acel fliker suparator.

Link spre comentariu

poti rezolva usor cu 74373, 74374, 74573 sau 74574 daca afisajul e facut din digiti separati. Cu 74573 sau 74574 cablajul se face mai usor deoarece au intrarile intr-o parte si iesirile in cealalta parte. Este nevoie de cate un circuit si 8 rezistente pentru fiecare digit. In felul asta se multiplica un port. Afisarea se face pe toti digitii odata si ia timp foarte scurt deoarece 74573 sau 574 merg la frecvente de minim 40MHz.

Link spre comentariu

incearca sa folosesti un modul dedicat, sunt relativ ieftine la 1.5 USD, si scapi de toata bataia de cap cu multiplexarea.

s-l500.jpg

Dacă vrei sa continui cu multiplexarea în Arduino, va trebui sa modifici toate funcțiile tale sa nu folosească delay(), adică non-blocking. Este destul de complicat, dar se poate face cu (multă) răbdare ...

Editat de deejay2k1
Link spre comentariu
Acum 22 ore, Elison a spus:

Initial n-am verificat daca libraria folosita suporta intreruperi, mai tarziu am vazut ca pentru  pentru ATmega 168 si 328 sunt suportate intreruperile generat de timerul 0,1 si 2. 
Am modificat putin codul din prima postare astfel incat sa se foloseasca, pentru multiplexare, intreruperea generata de timer 2.
Pe display la fiecare secunda este incrementat un contor incepand de la valoarea 1000.  
Verificati daca mai aveti acea palpaire.
 

Am testat codul, apare contorul, DAR si acel fliker.

Acum 19 ore, cimitavita a spus:

poti rezolva usor cu 74373, 74374, 74573 sau 74574 daca afisajul e facut din digiti separati. Cu 74573 sau 74574 cablajul se face mai usor deoarece au intrarile intr-o parte si iesirile in cealalta parte. Este nevoie de cate un circuit si 8 rezistente pentru fiecare digit. In felul asta se multiplica un port. Afisarea se face pe toti digitii odata si ia timp foarte scurt deoarece 74573 sau 574 merg la frecvente de minim 40MHz.

Poate incerc ceva cu 74HC595.

 

Acum 11 ore, deejay2k1 a spus:

incearca sa folosesti un modul dedicat, sunt relativ ieftine la 1.5 USD, si scapi de toata bataia de cap cu multiplexarea.

Acele module au pret mic, intradevar, dar au digitii prea mici, parca de 0,39 inch, am sa incerc cu 4 matrici 8x8 LED cu MAX7219

Acum 3 ore, Ionut Remus a spus:

http://www.qsl.net/yo6pir/rtc.html

Vezi in link cei 4 tranzistori pentru fiecare digit in parte si fa o adaptare pt ce ai nevoie, in principiu ar trebui sa ajute dar nu stiu cat!

Am sa testez, asa cum am scris si alimentarea digitilor, ori cu tranzistori, ori folosesc ceva integrate gen ULN2003 si ULN2803

 

Multumesc tuturor pentru implicare.

Ramane sa testez serile urmatoare, un ceas-termometru folosind DS18B20 , cu 4 matrici 8x8 led - MAX7219 ( le am pe stoc deja) si un Arduino Nano sau Uno.

 

 

Edit.

Am conectat un afisaj de 4 afisaje matrix 8x8 led-uri cu MAX7219, am incarcat codul de mai jos, DAR (iar un dar) nu merge ok.

Codul:

// Use the MD_MAX72XX library to scroll text on the display
//
// Demonstrates the use of the callback function to control what
// is scrolled on the display text.
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Speed for the display is controlled by a pot on SPEED_IN analog in.

#include <MD_MAX72xx.h>
#include <SPI.h>

#define  USE_POT_CONTROL 1
#define PRINT_CALLBACK  0

#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8

#define CLK_PIN   13  // or SCK
#define DATA_PIN  11  // or MOSI
#define CS_PIN    10  // or SS

// SPI hardware interface
MD_MAX72XX mx = MD_MAX72XX(CS_PIN, MAX_DEVICES);
// Arbitrary pins
//MD_MAX72XX mx = MD_MAX72XX(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Scrolling parameters
#if USE_POT_CONTROL
#define SPEED_IN  A5
#else
#define SCROLL_DELAY  75  // in milliseconds
#endif // USE_POT_CONTROL

#define CHAR_SPACING  1 // pixels between characters

// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE  75
char curMessage[BUF_SIZE];
char newMessage[BUF_SIZE];
bool newMessageAvailable = false;

uint16_t  scrollDelay;  // in milliseconds

void readSerial(void)
{
  static uint8_t  putIndex = 0;

  while (Serial.available())
  {
    newMessage[putIndex] = (char)Serial.read();
    if ((newMessage[putIndex] == '\n') || (putIndex >= BUF_SIZE-3)) // end of message character or full buffer
    {
      // put in a message separator and end the string
      newMessage[putIndex++] = ' ';
      newMessage[putIndex] = '\0';
      // restart the index for next filling spree and flag we have a message waiting
      putIndex = 0;
      newMessageAvailable = true;
    }
    else if (newMessage[putIndex] != '\r')
      // Just save the next char in next location
      putIndex++;
  }
}

void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col)
// Callback function for data that is being scrolled off the display
{
#if PRINT_CALLBACK
  Serial.print("\n cb ");
  Serial.print(dev);
  Serial.print(' ');
  Serial.print(t);
  Serial.print(' ');
  Serial.println(col);
#endif
}

uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t)
// Callback function for data that is required for scrolling into the display
{
  static char   *p = curMessage;
  static uint8_t  state = 0;
  static uint8_t  curLen, showLen;
  static uint8_t  cBuf[8];
  uint8_t colData;

  // finite state machine to control what we do on the callback
  switch(state)
  {
    case 0: // Load the next character from the font table
      showLen = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
      curLen = 0;
      state++;

      // if we reached end of message, reset the message pointer
      if (*p == '\0')
      {
        p = curMessage;     // reset the pointer to start of message
        if (newMessageAvailable)  // there is a new message waiting
        {
          strcpy(curMessage, newMessage); // copy it in
          newMessageAvailable = false;
        }
      }
      // !! deliberately fall through to next state to start displaying

    case 1: // display the next part of the character
      colData = cBuf[curLen++];
      if (curLen == showLen)
      {
        showLen = CHAR_SPACING;
        curLen = 0;
        state = 2;
      }
      break;

    case 2: // display inter-character spacing (blank column)
      colData = 0;
      curLen++;
      if (curLen == showLen)
        state = 0;
      break;

    default:
      state = 0;
  }

  return(colData);
}

 void scrollText(void)
{
  static uint32_t prevTime = 0;

  // Is it time to scroll the text?
  if (millis()-prevTime >= scrollDelay)
  {
    mx.transform(MD_MAX72XX::TSL);  // scroll along - the callback will load all the data
    prevTime = millis();      // starting point for next time
  }
}

uint16_t getScrollDelay(void)
{
#if USE_POT_CONTROL
  uint16_t  t;

  t = analogRead(SPEED_IN);
  t = map(t, 0, 1023, 25, 250);

  return(t);
#else
  return(SCROLL_DELAY);
#endif
}

void setup()
{
  mx.begin();
  mx.setShiftDataInCallback(scrollDataSource);
  mx.setShiftDataOutCallback(scrollDataSink);

#if USE_POT_CONTROL
  pinMode(SPEED_IN, INPUT);
#else
  scrollDelay = SCROLL_DELAY;
#endif

  strcpy(curMessage, "G E O M A R");
  newMessage[0] = '\0';

  Serial.begin(57600);
  Serial.print("\n[MD_MAX72XX Message Display]\nType a message for the scrolling display\nEnd message line with a newline");
}

void loop()
{
  scrollDelay = getScrollDelay();
  readSerial();
  scrollText();
}


Afisajul folosit:

MAX7219.jpg

 

De exemplu vreau sa afisez GEOMAR dar se vad in öglinda" literele ca in clip

 

Editat de GeoMar
Pentru a nu creea dublu post
Link spre comentariu

daca te uiti in datasheet o sa vezi ca MAX7219 are si iesire cu care poate comanda urmatorul MAX7219 s.a.m.d. Din film se vede ca programul care l-ai facut trimite GEOMAR doar la primul MAX7219. Apoi datele se duc la al doilea dar fara ultimii 8 biti. La fel se intampla si cu al treilea, dar fara ultimii 16 biti. Mai pe scurt: libraria folosita nu stie ca sunt legate 4 MAX7219 in serie ci crede ca e doar unul singur. Trebuie sa vezi daca libraria folosita permite legarea la mai multe MAX7219 in serie. Sau sa incerci sa trimita mai intai LSB si apoi MSB. Atat la biti cat si la octeti.

In asamblare chestia asta e foarte usor de facut.

Editat de cimitavita
Link spre comentariu

Incearca biblioteca MAX72xxPanel: https://github.com/markruys/arduino-Max72xxPanel

Este scalabila si poti seta rotatia

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>

#define pinCS 10 // Attach CS to this pin, DIN to MOSI and CLK to SCK (cf http://arduino.cc/en/Reference/SPI )
#define numberOfHorizontalDisplays 4
#define numberOfVerticalDisplays 1

Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

const String tape = "Ana are mere. Mici ! ";
#define wait 20 // In milliseconds

int spacer = 1;
int width = 5 + spacer; // The font width is 5 pixels

void setup() {

  matrix.setIntensity(1); // Use a value between 0 and 15 for brightness

  // Adjust to your own needs
  //  matrix.setPosition(0, 0, 0); // The first display is at <0, 0>
  //  matrix.setPosition(1, 1, 0); // The second display is at <1, 0>
  //  matrix.setPosition(2, 2, 0); // The third display is at <2, 0>
  //  matrix.setPosition(3, 3, 0); // And the last display is at <3, 0>
  //  ...
  matrix.setRotation(0, 1);    // The first display is position upside down
  matrix.setRotation(1, 1);
  matrix.setRotation(2, 1);
  matrix.setRotation(3, 1);    // The same hold for the last display
}

void loop() {


  for ( int i = 0 ; i < width * tape.length() + matrix.width() - 1 - spacer; i++ ) {

//    matrix.fillScreen(LOW);
//    matrix.write(); // Send bitmap to display

    int letter = i / width;
    int x = (matrix.width() - 1) - i % width;
    int y = (matrix.height() - 8) / 2; // center the text vertically

    while ( x + width - spacer >= 0 && letter >= 0 ) {
      if ( letter < tape.length() ) {
        matrix.drawChar(x, y, tape[letter], HIGH, LOW, 1);
      }

      letter--;
      x -= width;
    }

    matrix.write(); // Send bitmap to display

    delay(wait);
  }
}

 

Link spre comentariu
Acum 10 ore, cimitavita a spus:

daca te uiti in datasheet o sa vezi ca MAX7219 are si iesire cu care poate comanda urmatorul MAX7219 s.a.m.d. Din film se vede ca programul care l-ai facut trimite GEOMAR doar la primul MAX7219. Apoi datele se duc la al doilea dar fara ultimii 8 biti. La fel se intampla si cu al treilea, dar fara ultimii 16 biti. Mai pe scurt: libraria folosita nu stie ca sunt legate 4 MAX7219 ....

Codul este preluat dupa net cu librariile aferente. De unde am luat codul afisa ok.

Acum 3 ore, deejay2k1 a spus:

Incearca biblioteca MAX72xxPanel: https://github.com/markruys/arduino-Max72xxPanel

Este scalabila si poti seta rotatia

 

Am sa testez diseara si acest cod.

Multumesc la amandoi pentru ajutor.

Link spre comentariu
Acum 10 ore, deejay2k1 a spus:

Incearca biblioteca MAX72xxPanel: https://github.com/markruys/arduino-Max72xxPanel

Este scalabila si poti seta rotatia

Codul testat de mine este preluat de pe net, asa cum am mai mentionat, foloseste alte biblioteci, cu parere de rau nu am testat codul tau, am remediat defectul, remediu care il prezint mai jos, poate se lovesc si altii de aceasta situatie.

Am folosit in codul meu (preluat) librariile:

  • MD_Parola-master
  • MD_MAX72XX-master

Dupa ceva cautari pe net, am descoperit ca se poate remedia acea eroare de scrolling-afisare, prin simpla editare a unei singure linii din libraria MD_MAX72XX-master (probabil si alte librarii).
Am editat fisierul "MD_MAX72xx.h" cu ajutorul lui Notepad++, apoi am salvat, din informatiile gasite pe net, se pare ca am depistat modulul folosit de mine, este "FC16".
Aici am modificat in linia incercuita din foto, din "0"in "1"si acum scrollingul si afisarea este acum in regula:

Setari_librarie_MAx7219_Modificat_1_din_

 

Am facut si un mic test video, unde am folosit  8 module, nu 4 module, dupa cum se vede in clip si merge ok scrollingul-afisarea:

 

 

Ramane acum sa inteleg functionarea-afisarea cu MAX7219 si sa incerc sa adaug-afisez in cod un ceas cu RTC1307 si 2-3 temperaturi cu DS18B20.
Orice sfat-idee, sunt binevenite, asa cum am mai scris sunt incepator, trebuie sa le iau pe rand ca sa invat ceva si sa iasa ceea ce imi doresc eu.

 

Link spre comentariu

Revin cu ceva nelamuriri.

Am reusit sa realizez un ceas-termometru cu 3 senzori DS cu ajutorul lui Niq_ro (ii multumesc de sprijin/ajutor), functioneaza ok partea de ceas si partea de temperatura.
Astazi fiind ceva mai frig afara, am remarcat ca la temperaturi de sub 0 grade nu afiseaza corect. Nu vreu sa-l mai deranjez/stresez pe Niq_ro, de aceea apelez aici pe forum.

Partea de cod care se ocupa de afisarea temperaturii pe afisaj dotmatrix este:

[code]
//====== Temperatura 2 =========
  senzori.requestTemperatures();
  t2 = senzori.getTempC(senzor2);
  Serial.print("Temp C: ");
  Serial.println(t2);
  
  int t2a = 10 * t2;
  int tz2 = t2a / 100;
  t2a = t2a - tz2 * 100;
  int tu2 = t2a / 10;
  int ts2 = t2a % 10;

  Serial.print("=");
  Serial.print(tz2);
  Serial.print(tu2);
  Serial.print(",");
  Serial.print(ts2);
  Serial.println(" C");

  scrollMessage(temperatura2);
  if (t2a > 0)
  {
    loadBufferLong(43);  // +
  }
  else
  {
    loadBufferLong(45);  // +
    t2a = -t2a;
  }
  loadBufferLong(48 + tz2); // 2
  loadBufferLong(48 + tu2); // 1
  loadBufferLong(44);  // ,
  loadBufferLong(48 + ts2); // 7
  loadBufferLong(0x7F);  // degree sign
  loadBufferLong(67);  // C
  delay(2000);

[/code]

 

Temperatura citita de la senzorul DS este salvata initial in : "float t1;"

La temperaturi sub 0 grade asa afiseaza in comparatie cu alt ceas realizat de mine  :

Temp_matrix.jpg

temp_ceas.jpg

Link spre comentariu

Imi este greu sa inteleg bucata ta de cod fara context, dar mi se pare ca trebuia sa afiseze -01,3°C, dar ai gresit undeva cu schimbatul semnelor. 

Caracterul '/' este diametral opus fata de '0' (sau 48 in zecimal), la fel si '-' fata de '3' ASCII Table

Presupun deci ca tz2 si tu2 sunt negative atunci cand le aduni cu 48 ca sa obtii codul ascii afisat

 

incearca rapid modificarea asta:

  loadBufferLong(48 + abs(tz2)); // 2
  loadBufferLong(48 + abs(tu2)); // 1

sau mai bine pune lucrurile in ordine :)

//====== Temperatura 2 =========
  senzori.requestTemperatures();
  t2 = senzori.getTempC(senzor2);
  Serial.print("Temp C: ");
  Serial.println(t2);

  scrollMessage(temperatura2);
  if (t2 > 0.0f)
  {
    loadBufferLong(43);  // +
  }
  else
  {
    loadBufferLong(45);  // +
    t2 = -t2;
  }

  int t2a = 10 * t2;
  int tz2 = t2a / 100;
  t2a = t2a - tz2 * 100;
  int tu2 = t2a / 10;
  int ts2 = t2a % 10;

  Serial.print("=");
  Serial.print(tz2);
  Serial.print(tu2);
  Serial.print(",");
  Serial.print(ts2);
  Serial.println(" C");

  loadBufferLong(48 + tz2); // 2
  loadBufferLong(48 + tu2); // 1
  loadBufferLong(44);  // ,
  loadBufferLong(48 + ts2); // 7
  loadBufferLong(0x7F);  // degree sign
  loadBufferLong(67);  // C
  delay(2000);

 

Editat de deejay2k1
Link spre comentariu

Am incercat asa, dupa ce citeste temperatura t1 de la senzor , am setat eu in cod temperatura senzorului ca  t1= -11,9 (asta ca sa nu stau cu senzorul in frigider ca sa dea cu minus) si am testat pe serial.
La valoarea lui   t1 = -11.9  imi arata pe serial  -1-1.0

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări