![]() |
Forum Index : Microcontroller and PC projects : Need help using print and serial commands
Author | Message | ||||
lew247![]() Guru ![]() Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
As "some of you" will know I'm extremely new to microprocessors and such like I've got the 28pin Micromite on breadboard at the moment and I'm going to end up (hopefully) making a weather transmitter out of it and using a Micromite Plus indoors, I'm taking it one step at a time though, and I'm stuck on what is probably the easiest thing in the work for experienced users. I have the micromite and a DHT22 sensor and a HC-12 serial transciever connected at the moment, and I have a MPX4115A Pressure Sensor which will be connected to say pin 12 (com1 input) I have the DHT22 on pin 15 and the HC-12 on COM 2 How do I read the temp and humidity and send it to com 2 so I can read it on the computer where I have the other HC-12 connected? (I did it this way as it's easiest for me, I can check all stages are working before I need to even start on the Micromite+ ) I've read the manual but I'm having trouble putting it all together. I'm "guessing" that I would start with something like the following tell the Micromite where the DHT22 is connected to - which pin* Probably by something like this HUMID 15, temp, humid pause 3000 'wait 3 seconds before doing a second reading HUMID 15, temp, humid open "com2:9600" as #1 pause 500 'pause to make sure the serial port is open properly print #1 "the temperature is" temp "and the humidity is" humid close #1 How do I tell it that the pressure sensor is on pin 3 I'm guessing once I have that figured out I have to name the sensor as something, then it would be something like this (somehow) open "com1:9600 as #2 I'm stuck after this (and probably totally wrong before it) I have to read the input on com1 which is the pressure I then have to convert the reading to actual pressure with this formula Pressure = ((pressureValue/1024.0)+0.095)/0.000009 Then I have to print that on com2 probably by something like print #2 "the pressure is" pressure ' in between the temp/humidy print and closing com1 and then close com2 This is probably so easy for most of you but I think I'm totally lost The other question - does MMBasic not use line numbers? |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9594 |
Hey there. ![]() From the manual, page 58, it tells you how to setup the HUMID command, and the first parameter is the pin you have your sensor on - pin 15 in your example code. MMBASIC does use line-numbers, but they are strongly discouraged, as lineless code is much more structured and easy to work with ONCE YOU GET THE HANG OF IT. I speak from experience, as when I joined this forum, line-numbers were all I knew how to use, having never used lineless structured code before, but now that I do use it, I would never go back to line numbers. I think the latest versions of MMBASIC still support line numbers, but others here will be able to say for sure - I don't have a MM with the latest firmware loaded handy to me right now. You could try something like this: HUMID 3, temp, humid pause 3000 'wait 3 seconds before doing a second reading HUMID 3, temp, humid open "com1:9600" as #1 open "com2:9600" as #2 Do:Loop until LOC(#1)<>0 'Wait for pressure data P$=Input$(LOC(#1),#1) 'Save whatever is in COM1 buffer to P$ pressureValue=asc(P$) 'Convert data to number Pressure = ((pressureValue/1024.0)+0.095)/0.000009 Print #2,"The pressure is: "; Pressure print #2,"The temperature is " temp " and the humidity is " humid close #2 close #1 NONE OF THAT IS TESTED - I am just throwing ideas around. Your pressure sensor output is something we need to know - what format is it, how many bytes and what is it's output message protocol. My example code above assumes that the pressure data is a single byte, but it may well be more then that, and if so, the code example above won't work. I use com-port handles the same as the com port number to avoid confusion, so if com2, I use handle #2 rather then #1, but that is just me. You don't need to pause 500 when opening the ports - they are open as soon as the command executes. Sucking data out of the com port buffers uses the INPUT$ function, and assuming you need the data from the pressure sensor as a numeric variable rather then a string, I am converting the string variable to a numeric before throwing it at your pressure forumula, but you could do it all in one line PROVIDED the data from the pressure sensor is one single byte: Pressure = ((ASC(P$)/1024.0)+0.095)/0.000009 Remember that the COM ports are 8-bit ports, and as such, can't represent any one number bigger then 256, so it is quite possible that the pressure sensor is outputting multipule bytes that you have to combine into the likes of a 16-bit word or something. Need to have the pressure sensor details. ![]() EDIT: I've just had a quick search for the pressure sensor you mention, and it is not a serial device at all, so you need an analog input pin to read it's output voltage, so pretty much all example code above won't work, as I thought you had a sensor that used serial comms, with the mention of the pressure sensor on com1 kind of statement. ![]() You cannot use the com1 pins for the pressure sensor, as they do not measure analog voltage levels. Any of the pins marked as ANALOG can be used for this. Analog pins are dead easy to read, and you would use the likes of: pressureValue=pin(23) or combined all on one line: Pressure = ((Pin(23)/1024.0)+0.095)/0.000009, where pin23 is your pressure sensor input pin. Bear in mind that the analog input pins cannot have more then 3v3 on them, so any pressure above about 82kPa(11.8 PSI) will need protection against over-voltage on the input pin. If you never plan to see more then 80kPa for example, then you are probably safe enough directly connecting to the MM input pin. Smoke makes things work. When the smoke gets out, it stops! |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10254 |
Note that the MPX4115A is a b....r to read accurately with a uP. The output is extremely noisy. Read the datasheet and implement the filtering proposed there or something even better. FWIW, I prefer the BMP180. It needs a bit of maths to convert the data but it seems to give much more reliable readings. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9594 |
Something more along the lines of what you need would be: SetPin 23,AIN 'Configure pin23 for analog input HUMID 3, temp, humid 'Sensor on pin 3 pause 3000 'wait 3 seconds before doing a second reading HUMID 3, temp, humid open "com2:9600" as #2 Pressure = ((Pin(23)/1024.0)+0.095)/0.000009 Print #2,"The pressure is: "; Pressure print #2,"The temperature is " temp " and the humidity is " humid close #2 If you put your pressure sensor on pin 23, that should work, but I have not tested it. Smoke makes things work. When the smoke gets out, it stops! |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9594 |
@ matherp - interesting. If the output is noisy, which is not what the datasheet indicates, then it would be just about useless wouldn't it? You need a stable reference voltage or it's not worth it I would think, yes? As you say, perhaps your alternative would be much more advised. Have you done the maths to handle the data from that sensor, by any chance? Smoke makes things work. When the smoke gets out, it stops! |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10254 |
If you read it with a multimeter it is fine. Also, I've found "proper" ADCs read it OK with some sensible filtering so it is usable. However, the PIC ADCs are marginal at best. I assume the MPX4115A has some sort of internal clocking of its circuitry and that seems to conflict with the uP ADC Yes ![]() |
||||
lew247![]() Guru ![]() Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
Thanks everyone so far I do have a BME280 here, The reason I didn't use it was I tried it first on the serial input on the pc, and the temperature wasn't as exact as I'd have liked. I assume upon reading several reviews it's down to internal heating. I never thought of using just the pressure sensor part of it though. It might be easier to use that than the MPX4115A ? |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10254 |
The temperature measured by these sensors is used to calibrate the humidity reading. i.e. it needs to be the temperature of the humidity sensor itself |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6271 |
Like most users, I have settled on the DHT22 for temperature and humidity and the BMP085 (or BMP180) for pressure. Most humidity sensors go haywire after a period of very high humidity and need re-conditioning (or replacement). The Honeywell sensors I used previously lasted 2 - 3 years before being useless. This is the code I have running on my Micromite test server: ' reading the BMP085 pressure and DHT22 humidity sensors
' TassyJim 28 Oct 2014 OPTION clocktrim -4 DHT22pin = 26 ' 3.3V pins are OK for short leads <1 metre DIM BMPData(2) ' store data from BMP085 DIM cal(11) ' calibration data oss = 0 ' over sampling 0 to 3 alt = 240 ' your altitude in metres BMP085calMEM = &HAA ' start of 11 calibration values BMP085address = &H77 ' BMP085 address BMP085control = &HF4 ' BMP085 control register BMP085temp = &H2E ' BMP085 temperature command BMP085pres = &H34 ' BMP085 pressure command BMP085pres = BMP085pres + oss*&H40 ' adjust command for oversampling BMP085reading = &HF6 ' register for results of reading I2C OPEN 400, 200 ' Enable I2C. use slow speeds for long leads PAUSE 20 z = Calibrate() ' read the calibration data SETTICK 10000, doread PAUSE 1000 doread DO LOOP END SUB doread readhumidity t=temperature() p=pressure(oss) p0=Psl(p,alt) PRINT TIME$;" T(BMP085):";STR$(t,3,1);" P(sl):";STR$(p0/100,5,1); PRINT " T(DHT22): " STR$(TEMP,3,1);" H:" STR$(HUMID,3,1) 'PAUSE (30000) ' delay 30 seconds between readings END SUB FUNCTION Calibrate() ' needs to be called once for each module. ' safest to do it on every program start. LOCAL n, calMEM calMEM= BMP085calMEM FOR n = 1 TO 11 I2C WRITE BMP085address, 0, 1, calMEM ' first calibration location PAUSE 1 I2C READ BMP085address, 0, 2, BMPData(0) 'print BMPData(1), BMPData(0)*256 + BMPData(1) cal(n) = BMPData(0)*256 + BMPData(1) IF n < 4 OR n > 6 THEN ' need to convert some to signed numbers IF cal(n) > 32767 THEN cal(n) = cal(n) - 65536 ENDIF ENDIF 'print n,cal(n) PAUSE 1 calMEM=calMEM+2 ' advance to the next calibration location NEXT n END FUNCTION FUNCTION temperature() ' returns the temperature in degrees C to one decimal place LOCAL UT, x1, x2, b5 I2C WRITE BMP085address, 0, 2, BMP085control, BMP085temp PAUSE 5 I2C WRITE BMP085address, 0, 1, BMP085reading I2C READ BMP085address, 0, 2, BMPData(0) UT = BMPData(0)*256 + BMPData(1) 'calculate true temperature x1= INT( (UT-cal(6))*cal(5)/32768) x2=INT( cal(10)*2048/(x1+cal(11))) b5=x1+x2 temperature = INT((b5+8)/16)/10 END FUNCTION FUNCTION pressure(oss) ' returns the pressure in pascals. Divide by 100 for millibars ' recalculates the temperatre. ' time could be saved by reading the temperature once evry 10 minutes ' when taking readings at short intervals LOCAL UT, UP, x1, x2, x3, b5, b6, b7, pres, p pres = BMP085pres + oss*&H40 I2C WRITE BMP085address, 0, 2, BMP085control, BMP085temp PAUSE 5 I2C WRITE BMP085address, 0, 1, BMP085reading I2C READ BMP085address, 0, 2, BMPData(0) UT = BMPData(0)*256 + BMPData(1) I2C WRITE BMP085address, 0, 2, BMP085control, pres IF oss = 0 THEN ' different oversampling requires different PAUSE 5 ' reading times ELSEIF oss = 1 THEN PAUSE 8 ELSEIF oss = 2 THEN PAUSE 14 ELSE PAUSE 26 ENDIF I2C WRITE BMP085address, 0, 1, BMP085reading I2C READ BMP085address, 0, 2, BMPData(0) UP = BMPData(0)*256 + BMPData(1) I2C WRITE BMP085address, 0, 1, BMP085reading+2 I2C READ BMP085address, 0, 1, BMPData(0) UP=(UP*256+BMPData(0))/2^(8-oss) 'calculate true temperature x1= INT( (UT-cal(6))*cal(5)/32768) x2=INT( cal(10)*2048/(x1+cal(11))) b5=x1+x2 t=INT((b5+8)/16)/10 'print "Temperature: ",t 'calculate true atmospheric pressure b6 = b5 - 4000 x1 = INT((cal(8)*(b6*b6/4096))/2048) x2 = INT(cal(2)*b6/2048) x3 = x1 + x2 b3 = INT(((cal(1)*4+x3)*2^oss +2)/4) x1 = INT(cal(3)*b6/8192) x2 = INT((cal(7)*(b6*b6/4096))/65536) x3 = INT(((x1+x2)+2)/4) b4 = INT(cal(4)*x3/32768+cal(4)) b7 = INT((UP - b3)*(50000/2^oss)) p = INT((b7*2)/b4) x1 = INT(INT(p/256)*INT(p/256)) x1 = INT((x1*3038)/65536) x2 = INT((-7357*p)/65536) pressure = INT(p+(x1 + x2 + 3791)/16) END FUNCTION FUNCTION Psl(p, alt) 'given local pressure and altitude, returns pressure at sea level Psl= p/(1- alt/44330.77)^5.25588 END FUNCTION FUNCTION myAlt(p, p0) ' given local pressure (p) and pressure at sea level (p0) ' returns altitude in metres myAlt = 44330.77*(1-(p/p0)^0.190263) END FUNCTION SUB readhumidity DHT22 DHT22pin, TEMP, HUMID ' dump stale reading PAUSE 2000 ' time for the sensor to complete next read DHT22 DHT22pin, TEMP, HUMID ' this reading is only 2 seconds old 'PRINT TIME$;" Temperature: " STR$(TEMP,3,1);" Humidity: " STR$(HUMID,3,1) END SUB It prints the readings every 10 seconds but in real life, every 5 minutes is more realistic. All you need to do is change the PRINT to PRINT #2 Jim VK7JH MMedit |
||||
Bizzie Senior Member ![]() Joined: 06/07/2014 Location: AustraliaPosts: 192 |
TassyJim - Is there much variation in the quality of DHT22's? There seems to be quite a range of prices on the net. You mentioned HoneyWell should I try the buy these or some no brand name ones? Rob White |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6271 |
The Honeywell sensors are not the same as DHT22's. They have analog outputs and you have to do the maths to correct for temperature. They worked well for a couple of years but then gave strange outputs. When support for the DHT22 was added to MMBasic, I was quick to convert. I haven't been running DHT22's long enough to know how long they last in real life situations. I purchase cheap ones and carry a few spares. Jim VK7JH MMedit |
||||
Bizzie Senior Member ![]() Joined: 06/07/2014 Location: AustraliaPosts: 192 |
Thanks Jim, My brother and I were only talking about measuring RH this morning. The window each day for spraying crops is getting less each day as the last rainfall dries out. I will hook a sensor to an MM and take it for a drive on the spray rig and then compare with local static data. Thanks again. Rob White |
||||
lew247![]() Guru ![]() Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
TassyJim I don't suppose you know if that code would work with the BME280 sensor? |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6271 |
After a quick look at the datasheet, I would say that they are very different. The data sheet does have plenty of information and is written in good English so should be relatively easy to follow. Jim VK7JH MMedit |
||||
lew247![]() Guru ![]() Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
I did try reading and digesting the data sheet Yes its in extremely good English, but for a newbie like me it might as well be written in japanese I know nothing about registers or how to write bits of registers and so on, or what a data burst it, or 20-bit format Unfortunately I don't even know what a signed 32 bit integer is even though I tried researching it on Google |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6271 |
I have ordered a BME280 to play with. It will take 3 to 4 weeks to arrive and hopefully by then I will have a working computer again. If all that works out OK, I might have time to do the code before I go on holidays in April. Code for the BMP085 and DHT22 is available now if you want something to start experimenting with. Jim VK7JH MMedit |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |