Go Down

Topic: Issue with multithreading (Read 517 times) previous topic - next topic

FloWil

Having done quite a few programs for other mcu's, I would do such things like mutiplexing a display with an ISR (interrupt service routine)

As I do this in assembler I have no idea how that works with c++ and arduino (avr) but as far as I know, it will work quite easy.

Flo

GolamMostafa

#16
Apr 18, 2018, 11:04 pm Last Edit: Apr 19, 2018, 12:06 pm by GolamMostafa
8-digit cc-type 7-segment Multiplexed Display Unit.




Code: [Select]
#include <SimpleDHT.h>

int pinDHT22 = 2;
SimpleDHT22 dht22;

unsigned long presentmillis;

byte lupTable[] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71
                };  //cc-code for 0, 1, 2, 3, ........E, F              

byte ccArray[8];

void setup()
{
  Serial.begin(9600);
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  DDRB = 0xFF;
  DDRC = 0xFF;
}

void loop()
{
 while((millis()-presentmillis) <1500)
 {
    refreshDisplay();
 }
 presentmillis = millis();
 acqDHT22();
}

void refreshDisplay()
{
  byte y1 = 0b111111;
  byte y2 = 0b111111;
  for (int i=0; i<8; i++)
  {
    byte x = ccArray[i];
    PORTB = x;
    digitalWrite(6, bitRead(x, 6));
    digitalWrite(7, bitRead(x, 7));
    byte y3 = y1;
    bitClear(y3, i);
    PORTC = y3;
    //-----------------------------------------
    if (i <=5)
    {
      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
    }
    if (i == 6)
    {
      digitalWrite(4, LOW);
      digitalWrite(5, HIGH);
    }

    if (i == 7)
    {
      digitalWrite(4, HIGH);
      digitalWrite(5, LOW);
    }
    delay(2);
  }
}

void acqDHT22()
{
  float temperature = 0;
  float humidity = 0;
  dht22.read2(pinDHT22, &temperature, &humidity, data);
  
//---------------------------------------------------------
 unsigned long *ptr;
  ptr = (unsigned long*) &temperature;
  unsigned long m = *ptr;
 
  unsigned long m1 = m;
  m1 = m1 >> 23;
  unsigned long m2 = pow(2, m1-127);
  
  uint32_t dec=0;
  for (int i=22, j=-1; i>=0, j>=-23; i--, j--)
  {
    dec += (uint32_t)bitRead(m, i)*pow(2, j)*1000000;
  }

  dec = dec + 1000000;
  uint32_t dec1 = (uint32_t) m2*dec;
  
 /* --- alternate codes to convert the float into fixed point integer value : 27.80 ----> 2780
   temperature = temperature*100.00;   //say temperature = 27.80
   unit16_t dec1 = (uint16_t)temperature;  //dec1 = 2780 = 0x0ADC

*/

  byte inDex[8];
  for (int i=0; i<8; i++)
  {
    inDex[i] = dec1%10;
    dec1 = dec1/10;
  }

 for (int i=0, j=7; i<4, j>=4; i++, j--)
 {
    ccArray[i] = lupTable[inDex[j]];
 }

  ccArray[1] = ccArray[1]|0x80;        //place point
  
//-------------------------------------------------------
 unsigned long *ptrx;
  ptrx = (unsigned long*) &humidity;
  unsigned long mx = *ptrx;

  unsigned long m1x = mx;
  m1x = m1x >> 23;
  unsigned long m2x = pow(2, m1x-127);
  
  uint32_t decx=0;
  for (int i=22, j=-1; i>=0, j>=-23; i--, j--)
  {
    decx += (uint32_t)bitRead(mx, i)*pow(2, j)*1000000;
  }

  decx = decx + 1000000;
  uint32_t dec1x = (uint32_t) m2x*decx;
  
  byte inDexx[8];
  for (int i=0; i<8; i++)
  {
    inDexx[i] = dec1x%10;
    dec1x = dec1x/10;
  }

 for (int i=4, j=7; i<8, j>=4; i++, j--)
 {
    ccArray[i] = lupTable[inDexx[j]];
 }

  ccArray[5] = ccArray[5]|0x80;        //place point
  
  
}

lastchancename

#17
Apr 19, 2018, 05:18 am Last Edit: Apr 19, 2018, 03:51 pm by lastchancename
With post #16
ADD current limiting resistors!
DO NOT turn on multiple digits at the same time (even accidentally)
More than 2/3 simultaneously could damage the column output pin, and will dim the segments even if current limiting resistors are in place.
When posting - use the toolbar and read the stickies if you're not sure!  </code> tags are our friend!
You can lead a plug to an outlet, but you can't make them turn it on.

GolamMostafa

#18
Apr 19, 2018, 12:03 pm Last Edit: Apr 19, 2018, 12:04 pm by GolamMostafa
The diagram of Post#16 has been modified to include current limiting resistors for the segments. Thanks for the observation.  

Whandall

The action described in

The diagram of Post#16 has been modified to include current limiting resistors for the segments.
was noted as a violation of the forum rules/standards.  ;)

Never change technical parts of posts that have been commented in any way,
doing so makes the comments look unbased/stupid/strange, always post such changes in a new response.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

lastchancename

#20
Apr 19, 2018, 01:39 pm Last Edit: Apr 19, 2018, 01:39 pm by lastchancename
...doing so makes the comments look unbased/stupid/strange...
While this is perfectly correct, we are also very good at "looking unbased/stupid/strange"
When posting - use the toolbar and read the stickies if you're not sure!  </code> tags are our friend!
You can lead a plug to an outlet, but you can't make them turn it on.

sterretje

Code: [Select]
...
...

I think you're still missing where the bottleneck is. The read2 method calls the sample method that basically starts with a 20ms delay after which it reads the 40 bits (which takes up to about 5ms).

That 20ms needs to be implemented in a non-blocking way.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

AKJ

sterreje,

EXACTLY what i mean. Calling the Simple DHT library to read the values itself, delays the display to 20 ms, like shown in the screenshots i posted.

GolamMostafa,

i would applaud you, if you could upload a proof video of the displays actually working with the sensor.


sterretje

AKJ, have you managed to mod the library?
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

GolamMostafa

#24
Apr 20, 2018, 05:55 am Last Edit: Apr 20, 2018, 05:57 am by GolamMostafa
Quote
i would applaud you, if you could upload a proof video of the displays actually working with the sensor.
Co-operation is a vital concept in group work. I have added 4-digit block to display the temperature; you can add the remaining 4-digit block to display the humidity. The full program codes are there in the previous Post#16. You can also optimize the program codes.

Thanks,

AKJ

sterretje,

i was a bit too busy in the week. My C knowledge wasn't good enough to understand and manipulate the library. The following code however seems simple enough and i am trying to improve it, by removing the delay(30);

Code: [Select]


int DHpin = A1;
byte dat[5];
byte read_data(){
  byte data;
  for(int i = 0; i < 8; i ++){
    if (digitalRead(DHpin) == LOW){
      while (digitalRead(DHpin) == LOW); // wait for 50us;
      delayMicroseconds(30); // determine the duration of the high level to determine the data is '0 'or '1';
        if (digitalRead (DHpin) == HIGH)
          data |= (1 << (7-i)); // high front and low in the post;
        while (digitalRead (DHpin) == HIGH); // data '1 ', wait for the next one receiver;
    }
  }
return data;
}
void start_test(){
  digitalWrite(DHpin, LOW);
  delay(30); // delay greater than 18ms, so DHT11 start signal can be detected;
  digitalWrite(DHpin, HIGH);
  delayMicroseconds(40); // Wait DHT11 response;
  pinMode(DHpin, INPUT);
  while (digitalRead(DHpin) == HIGH);
  delayMicroseconds (80); // DHT11 a response, pulled the bus 80us;
  if (digitalRead(DHpin) == LOW);
  delayMicroseconds (80); // DHT11 80us after the bus pulled to start sending data;
  for (int i = 0; i <4; i ++) // receives temperature and humidity data, the parity bit is not considered;
  dat[i] = read_data();
  pinMode(DHpin, OUTPUT);
  digitalWrite(DHpin, HIGH); // sending data once after releasing the bus, wait for the host to open the next Start signal;
}
void setup(){
  Serial.begin (9600);
  pinMode (DHpin, OUTPUT);
}
void loop(){
   //bus down, send start signal;
  start_test();
  Serial.print("Current humdity =");
  Serial.print(dat [0], DEC); // display the humidity-bit integer;
  Serial.print('.');
  Serial.print(dat [1], DEC); // display the humidity decimal places;
  Serial.println('%');
  Serial.print("Current temperature =");
  Serial.print(dat [2], DEC); // display the temperature of integer bits;
  Serial.print('.');
  Serial.print(dat [3], DEC); // display the temperature of decimal places;
  Serial.println('C');
  delay(2000);
}


However, the sensor is really fragile, to the point where each modification i made, blocks the sensor and i need to restart the arduino or wait for a couple of minutes in order to reuse the sensor.

AKJ

I managed to solve it: I noticed that the sensor values were being read consistently well even with delay(24). So i delayed each display to delay(6) with didn't damage the frame rate (at least to the human eye), so that at the end of displaying, we have somewhat delay(24).

So i appended the displaying as delay for the sensor. It isn't multitasking.


Thank you all for your help. I will post the finish product in the project hub (still need to add and calibrate the Air quality sensor, which seems to already work since the values are analog).

GolamMostafa, it is almost similar to what you did in your code.

Clean Code (Missing, button Press and error codes):

Code: [Select]

int DHpin = A1;
byte dat[5];
int temperature, humidity;
boolean test = true;
boolean sensor = true;
const byte digit[10][7] = {{1, 1, 1, 1, 1, 1, 0}, //0
                           {0, 1, 1, 0, 0, 0, 0},
                           {1, 1, 0, 1, 1, 0, 1},
                           {1, 1, 1, 1, 0, 0, 1},
                           {0, 1, 1, 0, 0, 1, 1},
                           {1, 0, 1, 1, 0, 1, 1},
                           {1, 0, 1, 1, 1, 1, 1},
                           {1, 1, 1, 0, 0, 0, 0},
                           {1, 1, 1, 1, 1, 1, 1},
                           {1, 1, 1, 1, 0, 1, 1} //9
                           };
const byte symbol[3][7] = {{1, 1, 0, 0, 0, 1, 1}, // Degree
                           {1, 0, 0, 0, 1, 1, 1}, // Feuchtichkeit
                           {0, 0, 0, 1, 1, 1, 0}  // Air
                           };
const byte letter[2][7] = {{1, 0, 0, 1, 1, 1, 1}, // E
                           {1, 1, 1, 0, 1, 1, 1}  // R
                           };
const int led[8] = {9, 4, 3, 2, 6, 8, 7};
const int signPins[3] = {11, 12, 13};

unsigned long now, before, later;
int meas_val[3] = {0, 0, 0};
int disp_val[3] = {0, 0, 0};
int n = 1;

void Disp_digit(int var_1, int var_2){
  for (int i = 10; i < 14; i ++){
    if (i % 10 != var_1){
      digitalWrite(i, HIGH);
    }
  }
  digitalWrite(var_1+10, LOW);
  for (int i = 0; i < 7; i ++){
    digitalWrite(led[i], LOW);
    if (digit[var_2][i] == 1){
      digitalWrite(led[i], HIGH); 
    }
  }
  delay(6);
}
void disp(int var){
  for (int i = 11; i < 14; i++){
    digitalWrite(i, HIGH);
  }
  digitalWrite(10, LOW);
  for (int i = 0; i < 7; i ++){
    digitalWrite(led[i], LOW);
    if (symbol[var][i] == 1){
      digitalWrite(led[i], HIGH);
    }
  }
  delay(6);
  for (int i = 0; i < 3; i++){
    Disp_digit(3-i, disp_val[i]);   
  }
}

byte read_data(){
  byte data;
  for(int i = 0; i < 8; i ++){
    if (digitalRead(DHpin) == LOW){
      while (digitalRead(DHpin) == LOW); // wait for 50us;
      delayMicroseconds(30); // determine the duration of the high level to determine the data is '0 'or '1';
        if (digitalRead (DHpin) == HIGH)
          data |= (1 << (7-i)); // high front and low in the post;
        while (digitalRead (DHpin) == HIGH); // data '1 ', wait for the next one receiver;
    }
  }
return data;
}
void start_test(){
  digitalWrite(DHpin, HIGH);
  delayMicroseconds(40); // Wait DHT11 response;
  pinMode(DHpin, INPUT);
  while (digitalRead(DHpin) == HIGH);
  delayMicroseconds (80); // DHT11 a response, pulled the bus 80us;
  if (digitalRead(DHpin) == LOW);
  delayMicroseconds (80); // DHT11 80us after the bus pulled to start sending data;
  for (int i = 0; i <4; i ++) // receives temperature and humidity data, the parity bit is not considered;
  dat[i] = read_data();
  pinMode(DHpin, OUTPUT);
  digitalWrite(DHpin, HIGH); // sending data once after releasing the bus, wait for the host to open the next Start signal;
}
void setup(){
  Serial.begin (9600);
  pinMode (DHpin, OUTPUT);
  pinMode(2, OUTPUT); //D
  pinMode(3, OUTPUT); //C
  pinMode(4, OUTPUT); //B
  pinMode(5, OUTPUT); //DOT
  pinMode(6, OUTPUT); //E
  pinMode(7, OUTPUT); //G
  pinMode(8, OUTPUT); //F
  pinMode(9, OUTPUT); //A
  pinMode(A0, INPUT); //Button
  pinMode(A2, OUTPUT); //LED Red
  pinMode(A3, OUTPUT); //LED Green
  pinMode(A4, OUTPUT); //LED Blue

  pinMode(10, OUTPUT); //LED 4
  pinMode(11, OUTPUT); //LED 3
  pinMode(12, OUTPUT); //LED 2
  pinMode(13, OUTPUT); //LED 1
 
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);
}
void loop(){
  if (millis() - now > 2000 || test == true){
    digitalWrite(DHpin, LOW);
    sensor = true;
  }
  disp(n);
   if (sensor){
    start_test();
    meas_val[0] = dat[2];
    meas_val[1] = dat[0];
    disp_val[0] = int(meas_val[n] /100);
    disp_val[1] = int((meas_val[n] % 100)/10);
    disp_val[2] = int((meas_val[n] % 100) % 10);
    now = millis();
    Serial.println(meas_val[1]);
    test = false;
    sensor = false;
  }
 
}


Video Demo

Go Up