Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by DanielPHuber

  1. Hi Reaper, thanks a lot, I learned a thing ot two. There is nothing wrong with the library, I must have fooled myself yesterday. Anyway, today the library works with F(..). However, I do not yet understand fully what F(..) does on the MSP430. On the Arduino we have a Harvard architecture, that means separate address spaces for code and data. Therefore before using "print " to print a string in code segment, we must trick "print" into fetching the string from code and not data space. must first be copied into data segment. Here F(..) makes sense. However, MSP430 is von Neuman, that means there is only one single address space for both data and code. Therefore there is no problem accessing something in the code segment. What does F(..) in this case? Is F(..) on the MSP430 superfluous? Does it add superfluous code? thank's for the teaching, Daniel
  2. The following concerns Energia 0101E0017 on Windows 10 and EtherEncLib-0.4.2 Launchpad MSP-EXP430G2 with a MSP430G2553 Hi Reaper, thanks a lot for the library. However, I had a bad start. To begin with, I was not able to get the smallest answer from it. Of course, I suspected the SPI interface, but was barking up the wrong tree. Not until I began to dig into the library I stroke gold. The first problem was a function "F" used in print context like e.g. ? Serial.println(F("Text to print")) I never encountered this function bevor with MSP430G2553, I do not know what it does, but it compiles. However, after replacing all occurrences of this function , oh wonder, nearly everything worked! The second hickup I encountered, was the chip (or slave, CS or SS) select pin (in my case pin 10) in the examples. Although the sketch sets this to output mode, it does not set it to "LOW". Without setting this pin to low, I did not receive any answer from the library. I think the SPI started up in "slave" mode. This CS pin is rather finicky, I fail to understand it. The pin reference in "energia.nu" for MSP430G2553 specifies that the SPI library uses P2.0 as CS, but this dos not work, neither does P2.1. However P2.2 works, why? It would interesting if you could comment. cheers, Daniel
  3. Hi, I tried my hand for the first time on a servo and my experience may be helpful to other people. Servos are controlled by the length of a pulse. This pulse is repeated ca. every 20mS. The pulse length can vary coarsly between 1 and 2 mS. The pulse length determines the rotation angle. If the servo starts up, it goes to a middle position, corresponding to a ca. 1.5 mS pulse. For shorter pulses the servo turns in one direction, for longer pulses to the other. The range is limited, mostly to +/- 90 degree, the accurate values depend on the servo, as does the min/max widths. Mine had a range of a bit more than 180 degree for a min pulse width of 680 uS and a max width of 2.62 mS. However, you should not use these values but allow for some safety margin. Otherwise the motor may just not reach (e.g. due to slip or play) the position and the motor tries hard and gets hot. Most servos have 3 wires that are color coded from bright to dark, the color may change. The brightest is the signal pin where the pulses are fed. The middle one, mostly red, goes to Plus and the darkest one (brown, black..) goes to ground. Energia comes with a helpful server library. There an object: "Servo" is declared. You initiated the server by the method "attach". It comes in 2 varieties (assuming we declared an object "myservo"): myservo.attach(pinNo); myservo.attach(pinNo,minVal,maxVal); where pinNo means the launchpad pin number of the pin used to control the servo. min/maxVal are the minimal/maximal pulse width you want to use. This is not clearly described in the library and confused me bit. In further commands you can confortably deal with degrees beween 0 and 180. The library will transform the degree values into pulse widths, where 0 degree corresponds to the minimal pulse width and 180 degree to the max you specified. If you do not specify min/max values, some default values are used. In may case the lower default value could not be reached and the motor got hot. Therefore, it is better to determine correct values and specify these, using the second form of "attach". After initialization the servo goes to the 90 degree position. To send it to the 0 degree positio you would write: myservo.write(0); My servo did not respond quit linear. To send it to the 90 degree position I had to say 83 degree. Here is a small test program: // test for 9g Servo // 1. Button press -> 0 degree // 2. Button press -> 90 degree. Due due nonlinearity we need 83 degree // 3. Button press -> 180 degree. // 4. Button press -> 90 degree. #define sig P1_4 // signal for servo #define but P1_3 // button #define minWidth 770 // min pulse width in uSec of servo (680 allowed) #define maxWidth 2595 // max pulse width in uSec of servo (2620 allowed) #include <Servo.h> Servo myservo; void setup() { myservo.attach(sig,minWidth,maxWidth); pinMode(but, INPUT_PULLUP); } void loop() { while (digitalRead(but)); myservo.write(0); delay(500); while (digitalRead(but)); myservo.write(83);delay(500); while (digitalRead(but)); myservo.write(180);delay(500); while (digitalRead(but)); myservo.write(83); delay(500); } Note that due to nonlinearity of the servo I need to specify 83 degree for a 90 degree rotation. For test purposes you may power the servo directly from the launchpad (provided you do not have a monster servo with a hugh current consumption). In the enclosed picture I control the servo from launchpad pin P1_4 and power it directly from the launchpad. Have fun, Daniel
  4. Hi Robert, My happiness did not last long. Next morning that old problems were back!!!! Although it works fine with Win7 and Ubuntu, I gave it another try. The culprit seems to be the serial line monitor. Here is a workaround I found: Open some serial terminal, plug in the Launchpad and connect it to the terminal (you need to guess the correct COM port). Only now start Energia. Check if in the Energia preferences the serial line monitor is set to "false". Now you can compile and download. This seems to work, although I did not yet had time to test it thoroughly. There seems to be some unfinished business with Energia and Windows 10 (Microsoft seems to become some competition!). Maybe it is better to wait some time. I also mention that I tried the "cloud" feature of CodeComposer Studio 6. If it works, this should let you compile and upload from the Cloud, what would be a blessing considering the monstrous CCS6. Here the software seems not have reached a stage to be realeased. It screw up my MSP432 repeatedly so badly that a factory reset of the firmware was necessary. I also tried CCS6 on Win10 but also had troubles and decided to wait. One last note. The old control panel is still available in Win10. There you can find the "Devices and Printers". I think what shows up there are the XDS110 drivers needed for MSP432.
  5. I am banging my head and make slow progress. I could pin down the bug to the Serial library, the Serial.print command. As long as my program does not use the UART and Serial monitor, everything is fine. I can even initialize with "Serial.begin(9600)". I checked that the jumpers are set for "Hardware UART". Downloading also works, so I am no more sure if it is a driver problem. However, as soon as I send something with Serial.print from the Launchpad to the PC, Energia freezes for quit some time. If I prevent the Launchpad to send data by pressing the reset button, everything is fine, no freeze. If I program a button to send something, everything works fine until I press the button. Therefore, the UART communication is somehow blocking Energia! If I try to open the Serial monitor after a freeze I get the message: "Serial port COM11 already in use. Try quitting any program that my be using it." Therefore, it seems like download and Serial communication use different channels. I also tried the same thing with Ubuntu on the same machine. I see the same behavior !!! I also tried it with Windows 7 and it worked!! I also tried another Launchpad with no luck. Any ideas? cheers, Daniel
  6. Here is my environment: Windows 10 64 Energia 0101E0017 MSP430G2553 Launchpad version 1.5 I updated to Windows 10, downloaded and installed the drivers "EZ430-UART.zip" for the virtual serial port without an error message. When I plug in the Launchpad, it is recognised by the device manager as "USB serial device (COM11)". Under "Devices and printers" it is shown as "Texas Instruments MSP -FET43QUIF". Now, as long as the Launchpad is not yet plugged in, Energia works just fine. However, if the Launchpad is already plugged in when I start Energia it takes forever until the following error message appears: "Launch4j An error occured while starting the application" If you continue, the editor works normally, but the "Tools" menu reacts very, very slow (minutes!). But as soon as you unplug the Launchpad, the menu opens at once. The "Sketch" menu shows the same behaviour, but not always. To open a file takes for ever. Compilation proceeds normally, but nothing is uploaded! If you start Energia before the Launchpad is plugged in, there is no error message, Energia works fine until you plug in the Lauchpad. Then the strange behaviour as above appears. Well, it looks like a driver issue. Should I get another driver? A little help would be appreciated, Daniel
  7. Hello, thanks for the response, it is greatly appreciated. I happily arrived at a solution. It seemed that during the very first download some part of the memory was protected (I always suffer from too much security!) What finally brought the solution was the unprotection of memory by the procedure described in the CodeComposer 6.1 manual: slau575B. On page 22, section 7 "Device Security" the procedure is described. The draw back is that you need CodeComposer to do this. Maybe it can also be done using the Cloud, but I am not sure. There seems to be a further issue with firmware versions. Having used Energia and then CodeComposer, the CodeComposer complains about the firmware: ===================== Error connecting to the target: (Error -1040 @ 0x0) A firmware update is required for the debug probe. Click the "Update" button to update the firmware and connect to the debug target. DO NOT UNPLUG THE DEBUG PROBE DURING THE UPDATE. (Emulation package ============================ You are given the choice to update the firmware, what works and afterwards, you can download from CodeComposer. However, Energia seems to undo this update and next time you use CodeComposer we have the same issue again. cheers, Daniel
  8. Hi, thanks a lot for your reply: "a little help from a friend..." Unfortunately, I still get the following error message. New is the line: "Failed: Operation was aborted". Does this mean something with linking is wrong? Could it be that the firmware has been altered? Because the original out of the box code has also been erased or damaged by my first trial to download. Here is the error message: ================== >>>> Done <<<< xcopy E:\P\energia-0101E0017\hardware\emt\ti\runtime\wiring\msp432\configPkg\package\cfg\energia_*.rov.xs . /Y E:\P\energia-0101E0017\hardware\emt\ti\runtime\wiring\msp432\configPkg\package\cfg\energia_pm4fg.rov.xs 1 Datei(en) kopiert E:\P\energia-0101E0017\tools\common\DSLite\DebugServer\bin\DSLite load -c E:\P\energia-0101E0017\tools\common\DSLite\MSP432P401R.ccxml -f d:\tmp\build7606752871883565251.tmp\Blink.cpp.elf Failed: Operation was aborted Configuring Debugger (may take a few minutes on first launch)... Initializing Register Database... Initializing: CS_DAP_0 Executing Startup Scripts: CS_DAP_0 Initializing: CORTEX_M4_0 Executing Startup Scripts: CORTEX_M4_0 Connecting... fatal: CORTEX_M4_0: Error connecting to the target: (Error -1063 @ 0x0) Device ID is not recognized or is not supported by driver. Confirm device and debug probe configuration is correct, or update device driver. (Emulation package ================== I then tried to update the programmer from Energia but I get the following message: ========================== E:\P\energia-0101E0017\hardware\tools\msp430\mspdebug\mspdebug tilib --allow-fw-update "exit" MSPDebug version 0.22 - debugging tool for MSP430 MCUs Copyright © 2009-2013 Daniel Beer <dlbeer@gmail.com> This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. MSP430_GetNumberOfUsbIfs No unused FET found. =================================
  9. Hi, I just got a MSP432. I am working on Windows 7 64 bit. Upload to MSP430 does work, so I think Energia is o.k.. The problem are probably drivers. As upload did not work to MSP432, I updated to Energia 17, but this did not help. Then I updated drivers from: http://energia.nu/fi...110_drivers.zip This did not help either. I noticed that if I plug the MSP432, I get 2 virtual USB ports, not one as with MSP430, but this may be o.k.? From the utility xdfdsu -e I get following info about the drivers: ===================== VID: 0x0451 PID: 0xbef3 Device Name: XDS110 with CMSIS-DAP Version: Manufacturer: Texas Instruments Serial Num: 00000000 Mode: Runtime ======================== Here is the output I get from Energia (on both virtual ports): ================================ .... E:\P\energia-0101E0017\tools\common\DSLite\MSP432P401R.ccxml -f d:\tmp\build118977178168982942.tmp\sketch_jan07a.cpp.elf Configuring Debugger (may take a few minutes on first launch)... Failed: Operation was aborted Initializing Register Database... Initializing: CS_DAP_0 Executing Startup Scripts: CS_DAP_0 Initializing: CORTEX_M4_0 Executing Startup Scripts: CORTEX_M4_0 Connecting... fatal: CORTEX_M4_0: Error connecting to the target: (Error -1063 @ 0x0) Device ID is not recognized or is not supported by driver. Confirm device and debug probe configuration is correct, or update device driver. (Emulation package =================================== any help is appreciated, Daniel
  10. In between I found the excellent post from this forum : digitalReadFast and speed of digitalReadStarted by altineller, Aug 19 2014 05:41 PM and you bet, the problem was the "digitalRead". I replaced digitalRead(_CIN2) by: P1IN & 0b00100000) and it works. It is astonishing that for a CPU running with 16MHz, digitalRead is so slow. According to the above postdigitalRead takes approx. 18 uS what explains my problem.
  11. A decoder from a motor has 2 square wave outputs that deliver 256 pulses/revolution (duty cycle 1:1). The two outputs are 90 degree out of phase for direction information. I want to count pulse, in one direction up, in the other down. Towards this aim I attach to the first decoder output following routine: void countStep(){ if(digitalRead(_CIN2)){_pos++;} else {_pos--;} } "_CIN2" is the second decoder output and "pos" the counter variable. This works well until up to approx. 16kHz. But for higher frequencies it counts in the wrong direction. I first guessed, that the phase relation between the 2 signals is not constant, but an independent measurement showed it to be rock stable. Another guess is, that the interrupt is too slow (maybe because of the "digitalRead"). I am running a MSP430G2553 with 16MHz. Can somebody verify or falsify this guess?
  12. A display is a nice thing to have in many projects. A very cheap solution for only 2$ to 4$ is a 4 digit display from Qifei that can be found e.g. at www.Aliexpress.com. Of course, for this price you do not get a user manual! But what beats me is that I could not find a usable description on the internet. Therefore I had to rely on trial and error. Here is what I learned. The device has 2 cascaded 74HC595 shift registers, one for the digit select, the other for segements select. By this the deviceu can only display one digit at a time. Therefore, you must time multiplex the for digits fast enough that there is no flickering visible. Communication is serial, either by Bit banging or you may comfortably use the bult in SPI with the MSP430G2553 CPU. Energia is a very valuable tool for jobs like this. SPI will shift the data into the shift registers, but to output the data you have to shake (rising edge) the RCLK line, this will latch the output lines. Unfortunately this is not implemented in the Energia library for MSP430 (although the manual claims it) and you have to do it "by hand". Negative logic is used to display a digit. That is, a 1 bit switches the corresponding segment off. The segments of a single digit are numbered like: 0 5 1 6 4 2 3 7 where 7 is the decimal point. E.g. to display a 0 with a decimal point you would send: B01000000 The device has 5 input pins: Vcc: 3-5V Gnd DIO: the data signal SCLK: the clock signal, data will be read on the rising edge RCLK: on the rising edge of this signal the data and address will be latched to the output lines of the shift register Details of the interface can be seen in the following example program. It is a counter that counts 1/10 seconds. The interface is in the subroutine "set": // example for interfacing the 4 digit display from Qifei // 1/10 sec counter // The display can only show one single digit at a time. We // therefore need to time multiplex the display fast enough. #include <SPI.h> #define RCLK P2_0 // latch #define SCLK P1_5 // clock #define MOSI P1_7 // data to display //#define MISO P1_6 // data from peripherie, not used here const byte digit[] = //seven segment (+ 1 decimal point) bits { B11000000, //0 B11111001, //1 B10100100, //2 B10110000, //3 B10011001, //4 B10010010, //5 B10000010, //6 B11111000, //7 B10000000, //8 B10010000, //9 B10001000, //A B10000011, //b B11000110, //C B10100001, //d B10000110, //E B10001110 //F }; byte colDig[4] = // digits { B00000001, // digit 1 B00000010, // digit 2 B00000100, // digit 3 B00001000, // digit 4 }; byte dp= B01111111; //Decimal point. AND (&) with data byte empty= B11111111; // clear void setup() { pinMode (RCLK, OUTPUT); digitalWrite(RCLK,LOW); SPI.begin(); // SPI.setDataMode(SPI_MODE0); //default // SPI.setBitOrder(MSBFIRST); //default } void loop() { int del=1; long val=millis(); //decimal while(val>=1000000L) val-= 1000000L; int t1= val/100000L; val-= t1*100000L; int t2= val/10000L; val-= t2*10000L; int t3= val/1000L; val-= t3*1000L; int t4= val/100L; val-= t4*100L; // hexadecimal /* val/=100; int t1= val/4096L; val-= t1*4096L; int t2= val/256L; val-= t2*256L; int t3= val/16L; val-= t3*16L; int t4= val; */ for(int i1=0;i1<4;i1++){ set(digit[t1],colDig[3]);delay(del); set(digit[t2],colDig[2]);delay(del); set(digit[t3] & dp,colDig[1]);delay(del); set(digit[t4],colDig[0]);delay(del); set(empty,colDig[0]); } } // set one digit void set(byte val, byte dig){ digitalWrite(RCLK,LOW); SPI.transfer(val); // value SPI.transfer(dig); // which digit digitalWrite(RCLK,HIGH); } Note that there is a similar device with the TM1637 chip that is different from what I described here.
  13. DanielPHuber

    LCD Game

    Everybody here certainly loves the MSP430LaunchPad. But its is not easy to communicate info from the controller to the outside world. To switch some LED on and off is the most you can easily do. Larsie (Lars Kristian Roland), a member of this forum made a wonderful project, a LCD booster back for the MSP430: http://www.43oh.com/forum/viewtopic.php?f=9&t=2138 These are available in Larsies shop or in the 43oh shop. I lately bought one of thouse. To learn how to program the LCD controller, I first made some font demos and then the game here. For an interactive game you need some buttons. On Larsies booster pack there is space for 4 small push buttons. I did not have buttons this small. Instead I made a small board with 4 larger buttons and connected them with a small ribbon cable. The game displays a good guy icon (you) and several bad guys icons. You can cotrol the good guy using the for four buttons. The bad guys move around and you must try to avoid them. If a bad catches you, the game is finished. At the beginning, you may choose 4 levels from easy to hard. ====> The code for the MSP430LaunchPad can be found here: <====== https://sites.google.com/site/msp430game/EscapeGame.zip Here are some pictures: The "key board" The start screen The game screen:
  14. Hi kenemon, I actually use an expansion tank, otherwise the system would crack (see pictures). At first thought it seems ridiculous that the tank consist of an upside down PET bottle. But if you dig in, you will find that these PET bottles are rated for an unbelievable 15bar. I have some experiences with these bottles, I used them to build "water rockets" for the kids. These consists of an upside down bottle, approx. half filled with water. You then pump them up with air (we used 7bar from a compressor or a bicycle pump) and then you let go. These "rockets" fly approx. 30m high and are fun for the whole neighborhood. An additional benefit is that the bottles are transparent, you can actually see how the water expands, what is not little (good lecture in physics!). One bottle works, but next time when I empty the system, I will add a second bottle, because the pressure changes still a bit too much for my taste. However, at this time the system is filled with antifreeze (car supply) what makes it a bit of a mess to empty. Therefore, I wait until I have to empty it anyway. In Switzerland you pay ridiculous prices for copper at this time. However, I am living not too far from Germany, where you can get it much cheaper. Most of the copper I could buy from surplus material and I payed something over SFr. 100.- for one collector. The tubing from the collector is done in PEX-Aluminium tubing, what is also much cheaper in Germany, I bought it for approx. 1 Euro/m. What do you mean by GFI? Ground Fault Interrupter? The main voltage part is separated from the low voltage part by an opto. Therefore, there is no direct connection between both sub-systems. By PEG, you main antifreeze? I need this dearly, two weeks ago we had -15 degree Celsius, but everything worked perfectly. As soon as the sun comes out, the boiler starts to heat. I do not think that circulating the water would prevent it from freezing with such low temperatures. cheers, Daniel
  15. Hi Kenemon, the storage was a problem as I did not have the necessary space. Therefore, I needed another solution. The original installation had a small electrical boiler. I installed a second boiler in serie with the original one. Thereby, the electrical boiler receives water preheated by the solar collector. If there is not enough sunshine, the water temperature will be boosted by electricity during night time. If the sun shines long enough, no electricity is used. Of course I can not store heat for a long time, it is used on a daily basis. For cut off, I monitor the temperature difference over the heat exchanger. If this becomes too small, it means that no heat is delivered to the boiler or even drained and I switch off the pump. I heat the boiler as soon as the collector is warmer than the boiler. For security reasons, I also have a max. boiler temp. where the pump is switched off, but I have not yet reached it. I soldered where appropriate because it is easier to do. Only where I had steel I did braze. It is important to have copper sheet metal with a coating that absorbs visible light, but does not re- radiate infrared heat. The copper sheet metal is soldered to copper tubing because of heat flux. The auxiliary tubing was first done with PETX tubing (cross linked PET with a aluminium layer), but it turned out that with a temperature of 120 degree C, these started to leek at the connectors. Therefore, I did all the tubing inside the collector in copper. The tubing from the collector to the basement is done in PETX, isolated with PET. This seems to work well. The only problem I had was, that the water immediately at the outlet is so hot, that the PET isolation melted. Therefore, I isolated the first meter using glass wool. The isolation of the collector at the back side is done in rock wool. The front is covered with a polycarbonat sheet. This is much cheaper than glass and does not break. In addition it can be bent easily using a hot air gun. cheers, Daniel
  16. I wanted to try out myself how well solar energy really works. Toward this aim I built a solar collector system for waterheating. A small boiler with a heat exchanger is used for heat storage and a ordinary heating pump for the water circulation. Temperature is measured at the collector, at the entrance and outlet of the heat exchanger and inside the heat storage boiler. As a controller for the pump I used an MSP430 launchpad. There were several problems I had to solve. First, temperature must be measured with a resolution of at least 1 degree. My preferred temperature sensor would have been a Pt100. This sensors are accurate and linear, but not very sensitive. With a 8 bit AD converter, a resolution of not more than 4 degree is possible, not good enough. Therefore I was forced to use NTC sensors. These are more sensitive, but not very accurate and the resistance changes with temperature not linearly, but exponentially. When I tried this out, I had to realize that the exponential function of C uses too much memory. Therefore, I had to find a replacement and I used a rational approximation that uses much less space and works satisfactorily accurate. Further, as the NTC sensors are not accurate enough, I had to measure the value of each and correct by software. To supervise the working of the controller I transmit the temperature values, the state of the pump and what action is taken to a PC that can be connected to the launchpad. This is actually not needed for the working of the controller, but it is nice to have a mean to see what is going on. Here is how the program works: After initialization we enter an infinite loop, that does the actual work. - First all 4 temperature values are measured. According to these values we decide what to do. - If the boiler temp is too high, we switch the pump of for security reasons. - If the pump is off and the collector temp is higher than the boiler temp by some margin and the collector temp is above some minimal value, we switch the pump on. - If the pump is on, we compare the entry and outlet temp of the heat exchanger. If these differ less than some value, that is, practically no heat is put into the boiler, we switch the pump off. - Finally we toggle a LED every 1 sec to indicate that the controller is working and wait 1 minute before we start the next cycle. To make the temperature measurement more reliable, I measure the temp 8 times and take the average. To minimize current consumption I put the CPU to sleep during wait. This controller now works for more than half an year to my full satisfaction. I get approx. 0.75 kW / m^2 heating power on a sunny day. I only regret, that we do not have more sunny days here in Switzerland. And here is the program that uses up nearly every bit of the 2K memory: ======================================================= /* Solar collector controller * Daniel Huber 1.7.2011 daniel_huber@sunrise.ch * * Measures Pin 1.3,1.4,1.5,1.7 with average * Calculates temperatures from measured values * If boiler temp too high -> do nothing * If collector temp > boiler+ TDelCol switch on pump, wait 1 min. * If temp of heatexchanger input < heat exchanger output+TDelEx switch off pump, repeat * send values to RS232 */ #include "msp430g2231.h" #include "stdbool.h" #include "stdlib.h" #include "math.h" #include "string.h" #define Tcm 110 // max temp at collector #define Tcmin 30 // min temp at collector #define Tbm 90 // max temp at boiler #define TDelCol 5 // min. temp between Collector and Boiler #define TDelEx 2 // min. temp between heat exchanger in and out #define TXD BIT1 // TXD on P1.1 #define Bit_time 104 // 9600 Baud, SMCLK=1MHz (1MHz/ 9600)=104 #define LEDR BIT0 // LED red #define LEDG BIT6 // LED green #define CHCOLLECT INCH_4 // measure channel collector #define CHHEATEXIN INCH_5 // measure channel heat exchanger #define CHHEATEXOUT INCH_3 // measure channel heat exchanger #define CHBOILER INCH_7 // measure channel boiler // pump on/off #define PumpOn {P1OUT |= BIT0;PumpOnFl=true; } #define PumpOff {P1OUT &= ~BIT0;PumpOnFl=false; } unsigned char BitCnt; // Bit count, used when transmitting byte unsigned int TXByte; // value sent over UART when Transmit() is called int i,j; // 'for' loop variable int TCol,TExIn,TExOut,TBoiler,channel; // Measured ADC Value bool PumpOnFl; // pump on flag unsigned int ADCValue; // aux. value to return value from interrupt short state; // state variable char msg[3]; float cor,R; // Function Definitions void Transmit(); //transmits a byte int Single_Measure(); //measures with avarage void Single_Measure0(); //measure single value void TransmitRecord(/*int TCol,int TExIn,int TExOut,int TBoiler,bool PumpOnFl*/); // transmit one record void delay1(); //delays 1 sec int P2T(int P); // ADC value to degree void main(void) { WDTCTL = WDTPW + WDTHOLD+WDTCNTCL; // Stop WDT: PWD,Hold, Counter Reset BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // SMCLK = DCO = 1MHz // BCSCTL3 |= LFXT1S1; // sets LFXT1Sx to 0b10, VLO mode, bit not set-> 32KHz BCSCTL3 |= XCAP_2; // set 10pF for cristal oscillator P1SEL |= TXD; // Connect TXD to timer pin P1DIR |= TXD | LEDR | LEDG; // use TX PumpOff; // Pump off state=1; __bis_SR_register(GIE); // interrupts enabled while(1){ msg[0]='\0'; // empty string cor=1.01*10.12;channel=CHCOLLECT; //correction factor: TCol=P2T(Single_Measure()); // collector temp cor=1*10.32;channel=CHHEATEXIN; TExIn=P2T(Single_Measure()); // heat exchanger in temp cor=0.89*10.21;channel=CHHEATEXOUT; // 0.937 takes care of R20 difference TExOut=3+P2T(Single_Measure()); // heat exchanger out temp, correct for NTC tolerance cor=1*10.32;channel=CHBOILER; TBoiler=P2T(Single_Measure());// boiler temp if (TBoiler > Tbm && state!=0) {PumpOff;state=0;strcat(msg,"st00");} switch(state){ case(0): if(TBoiler case(1): if((TCol>TBoiler+TDelCol) && TCol>=Tcmin) {PumpOn; state=2;strcat(msg,"12");} break; case(2): if(TExIn } TransmitRecord(); for(i=1;i<60;i++){ P1OUT ^= LEDG; // toggle LED at P1.6 delay1(); } } } // transmit one record void TransmitRecord(){ unsigned int k; i=0; while(i>=0){ switch(i){ case(0): k='SS'; break; case(1): k='tt'; break; case(2): k=TCol; break; case(3): k=TExIn; break; case(4): k=TExOut; break; case(5): k=TBoiler; break; case(6): if(PumpOnFl)k=1; else k=0; break; case(7): if (strlen(msg)>0){k=256*msg[1]+msg[0]; break;} else {i++;} case(8): k='EE'; break; case(9): {k='nn'; i=-2;} }; TXByte = (k & 0x00FF); // Set TXByte Transmit(); // Send TXByte = k >> 8; // Set TXByte to the upper 8 bits TXByte = TXByte & 0x00FF; Transmit(); i++; } } // averaged single measurement int Single_Measure(/*int channel*/){ int ADCAvg = 0; for (i = 0; i < 8; i++){ // add up values Single_Measure0(channel); ADCAvg += ADCValue; } ADCAvg >>= 3; // divide by 8 return ADCAvg; } /** * Reads ADC channel once, using AVCC as reference. **/ void Single_Measure0(/*int channel*/) { ADC10CTL0 &= ~ENC; // Disable ADC ADC10CTL0 = ADC10SHT_3 + ADC10ON + ADC10IE; // 64 clock ticks, ADC On, enable ADC interrupt ADC10CTL1 = ADC10SSEL_3 +channel; // Set 'chan', SMCLK __delay_cycles(1000); ADC10CTL0 |= ENC + ADC10SC; // Enable and start conversion _BIS_SR(CPUOFF + GIE); // sleep CPU } /** * Transmits the value currently in TXByte. The function waits till it is * finished transmiting before it returns. **/ void Transmit() { TXByte |= 0x100; // Add stop bit to TXByte (which is logical 1) TXByte = TXByte << 1; // Add start bit (which is logical 0) BitCnt = 0xA; // Load Bit counter, 8 bits + ST/SP CCTL0 = OUT; // TXD Idle as Mark TACTL = TASSEL_2 + MC_2; // SMCLK, continuous mode CCR0 = TAR; // Initialize compare register CCR0 += Bit_time; // Set time till first bit CCTL0 = CCIS0 + OUTMOD0 + CCIE; // Set signal, intial value, enable interrupts while ( CCTL0 & CCIE ); // Wait for previous TX completion } /** * ADC interrupt routine. Pulls CPU out of sleep mode. **/ #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR (void) { ADCValue = ADC10MEM; // Saves measured value. __bic_SR_register_on_exit(CPUOFF); // Enable CPU so the main while loop continues } /** * Timer interrupt routine. This handles transmitting and receiving bytes. **/ #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { CCR0 += Bit_time; // Add Offset to CCR0 if ( BitCnt == 0) // If all bits TXed { TACTL = TASSEL_2; // SMCLK, timer off (for power consumption) CCTL0 &= ~ CCIE ; // Disable interrupt } else { CCTL0 |= OUTMOD2; // Set TX bit to 0 if (TXByte & 0x01) CCTL0 &= ~ OUTMOD2; // If it should be 1, set it to 1 TXByte = TXByte >> 1; BitCnt --; } } /** * function to get temperature from measured ADC value **/ int P2T(int P){ #define P0 0x3FF R=cor*P/(P0-P); return( (159.444F+R*(29.4008F-0.21077F * R))/(1+R*(0.59504F+0.0155797F * R)) ); } //put CPU to sleep for 1 sec void delay1(){ IE1 |= WDTIE; // Watchdog Interrupt Enable WDTCTL = WDTPW+WDTTMSEL+WDTSSEL; // Passwd(WDTPW), Counter-Mode //Intervall(WDTTMSEL),Timer= "0"(WDTCNTCL), //SourceClk=ACLCK(WDTSSEL),Sel:00=Clk/32768 01=Clk/8192 10:Clk/512 11=Clk/64 _BIS_SR(LPM3_bits + GIE); // put CPU to sleep LPM1_bits } // delay interrupt routine, wakes up CPU #pragma vector=WDT_VECTOR __interrupt void WATCHDOG_ISR (void){ // interrupt routine for delay WDTCTL = WDTPW + WDTHOLD+WDTCNTCL; //Password(WDTPW), //Watchdog stop(WDTHOLD),Counter=0, this resets register(exeption: hold bit) // IE1 &= ~WDTIE; // Watchdog Interrupt Disable __bic_SR_register_on_exit(LPM3_bits); // clear LPM3 bits so the main while loop continues } ========================================================
  • Create New...