I thought of somehow playing around with the DS18B20 sensors. And not just to get the temperature values (which everyone can do), but somehow to visualize it. There was a simple idea. We put a webcam. We light the light on an even frame, on an even one - simmer. Subtract the picture - only the flash remains. On it and look for the location of the sensor, which is physically attached to the LED in space. And then the mathematical processing. Well, all this in the simulator. Under the cut described how to get beautiful pictures. And for those who do not want to understand - I suggest to look at the experiments at the end of the article.


int main(void) { const uint8_t ROM[][sizeof(ROM_T)] = /* ROM array */ { {0x26, 0x00, 0x00, 0x04, 0x4B, 0x15, 0x89, 0x28}, // 0 {0x71, 0x00, 0x00, 0x04, 0x4A, 0xC0, 0x65, 0x28}, // 1 {0xA5, 0x00, 0x00, 0x04, 0x4A, 0xCB, 0xCE, 0x28}, // 2 {0x41, 0x00, 0x00, 0x04, 0x4A, 0xAC, 0x65, 0x28}, // 3 {0x22, 0x00, 0x00, 0x04, 0x4B, 0x06, 0x0D, 0x28}, // 4 {0x86, 0x00, 0x00, 0x04, 0x4A, 0xF6, 0x46, 0x28} // 5 }; uint8_t nDevices = sizeof(ROM) / sizeof(ROM_T); /* Number of DS18B20 devices */ initUART(MYUBRR); /* Initialization of UART with appropriate baudrate */ initTimer0(); /* Initialization of Timer/counter0 */ initLED(nDevices); /* Initialization of LEDs */ { /* DS18B20s initialization */ uint8_t nDevices = sizeof(ROM) / sizeof(ROM_T); /* Number of DS18B20 devices */ ROM_T *pROM = (ROM_T *)&ROM; /* Pointer to ROM array */ initDQ(); /* Initialization of DQ pin */ while (nDevices--) /* For all DS18B20 */ initDS18B20(pROM++, RESOLUTION_11BIT); /* Initialization of DS18B20 with appropriate resolution */ } sei(); /* Global enable interrupts */ while (1) /* Infinite loop */ { sendTemperatureToUART((ROM_T *)&ROM, nDevices); /* Execute function routine */ } }  volatile uint8_t ledID = 0; /* Current ledID value */ volatile uint8_t ledID_prev = 255; /* Previous ledID value */ volatile uint8_t duration = FLASH_DURATION; /* Flash duration value */ ISR(USART_RXC_vect) /* UART interrupt handler */ { ledID = UDR; /* Assign ledID to receive via UART value */ if (ledID != ledID_prev) /* If current ledID equal to previous value */ { turnOnLED(ledID); /* Turn on the ledID LED */ timer0Start(); /* Start Timer0 */ ledID_prev = ledID; /* Previous ledID assign to current */ duration = FLASH_DURATION; /* Update LED flash duration */ } } ISR(TIMER0_COMP_vect) /* Timer0 compare interrupt handler */ { if (--duration == 0) /* Decrement Duration value each 1ms and if it reach to 0 */ { timer0Stop(); /* Stop Timer0 */ turnOffAllLED(); /* Turn off all LEDs */ timer0Clear(); /* Clear Timer0 counter register */ } } 
 Blocks of a COM port are marked in yellow. Separately transmitter, receiver and configurator. Port settings must match exactly the microcontroller (speed, parity, number of bits, etc.). The receiver receives the temperature, grouping it into a one-dimensional array of size [n 1] of type int16 , where n is the number of DS18B20 (I have 6). Each element of this array is further divided by 16 . This is from datasheet page 6. The transmitter sends the current Counter value. It just lights a certain LED. Ticking from 0 to n . Period 2 sample. Blue are the blocks responsible for displaying / saving the video stream. Green - blocks receiving video. Actually the webcam itself. There are a lot of settings, different, depending on the manufacturer. The picture is issued in gray tones. That's more interesting. The Diff block makes the difference between the previous and current frames. The Downsample odd block highlights only the difference lit — not the lit LED, but not vice versa. The Downsample block even skips only those frames in which the LED is extinguished.
 Violet grouped blocks for obtaining 2D Gaussians . We need two: Interference and Opacity . Different sigma. Their center is at the maximum point (where the LED was on). The coordinates are located in the Maximum block. Instead of constantly generating such Gaussians (and the exponent is a very time-consuming mat. Operation), it was decided to cut them out. For this, in the m-file, two Int and Op are generated with dimensions 2 times larger with the center in the middle, of which, further, the necessary branches are simply sprinkled with Crop interference and Crop opacity blocks.
 These two modules are identical. At the input Address is the cell number where the input Gaussian is written. Comes from the counter. Coincides with the number of the burning LED. The Delay module of the LEDs module serves for additional synchronization (while the picture arrives, the counter has time to ottikat). So everything is synchronized. The Enable signal enables writing. It is true if the maximum value is above the threshold (see the Maximum and Threshold block of the LEDs module). If the value is false, the content of the cell does not change. At the exit, everything is glued together in the third dimension. It turns out such a sandwich size [HW n] , where HxW is the resolution of the webcam, and n is the number of sensors / LEDs.
 Green is Opacity processing. We summarize the input array in the third dimension. Normalize it to the maximum. Multiply by the value of gain (from 0 to 1) (1) . Total we have an array with Gaussians superimposed on each other and maximum gain . Used as a factor for image blending. Red — Get a color temperature map. There is a slightly different math, all the same Gaussians. Described by the formula (2) . Roughly speaking, the temperature at an arbitrary point is the weighted average of all sensors. But the influence of each sensor as a percentage is proportional to the value of the Gaussians in it. The sum of all is taken as 100%.
 It remains to consider how the temperature distribution turns into a color map. The fact that circled in blue turns the specific temperature into a value between 0 and 1. In the red zone, the Prelookup block calculates the index by which the red, green, and blue value is searched. An array of colors contains 64 values. Intermediate are calculated by interpolation. Of the features there are two modes: relative and absolute. In the relative coldest and hottest place corresponds to the minimum and maximum of the input array. In the absolute - some constant values. In the first, it is more convenient to look at the temperature distribution profile. In the other - her absolute changes. H = 480; % Height of image W = 640; % Width of image minT = 20; % Min temperature maxT = 25; % Max temperature sigmaInt = 40; % Sigma interference sigmaOp = 80; % Sigma opacity gain = 1.0; % Gain value T = 0.3; % Threshold value nAvr = 8; % number of means % ------------------------------------------------------ [M,N] = meshgrid(-W:W, -H:H); % Meshgrid function R = sqrt(M.^2 + N.^2); % Distance from the center Int = normpdf(R, 0, sigmaInt); % 2D gaussian for interference Op = normpdf(R, 0, sigmaOp); % 2D gaussian for opacity Int = Int/max(max(Int)); % Normalization of interference gaussian Op = Op/max(max(Op)); % Normalization of opacity gaussian clear MNR sigmaInt sigmaOp % Delete unused variables from memory load('MyColormaps','mycmap'); % Load colormap 
 the picture degenerates into some sort of Voronoi partition . With 
 the whole map will be of the same color as the average, from all sensors, temperature. With an increase - the boundaries are blurred.Source: https://habr.com/ru/post/390985/
All Articles