Jump to content
43oh

CorB

Members
  • Content Count

    288
  • Joined

  • Last visited

  • Days Won

    5

Reputation Activity

  1. Like
    CorB got a reaction from dacoffey in MSP430 meets LaCrosse Temperature/Humidity sensor TX3TH   
    Hi,
     
    Excuses for the long post !!
     
    After I found out that I could detect signals in the 433Mhz band using an AIR Boosterpack (See viewtopic.php?f=9&t=2944 AIR Boosterpack RF spectrum display) I wanted to display the data I was receiving on the 433 Mhz band.
    Ive got a Lacrosse temperature/humidity logger WS8610 that can read up to 3 external sensors and log the data. These sensors broadcast their data every minute or so.
     
    Since I have a logger and I have a display you might ask why do you want to read the data ? My motivation for this is simple, the datalogger can only capture data for about 1.5 weeks and then the oldest readings are overwritten and I need to connect the datalogger to an old PC (that still has a USB-DB9 connector) to be able to store the data. If I can read the data directly from the sensors I can hook them up in a system I allready have running with several other sensors (gas, electricityusage, inside temperature) and store the data on the internet. For those that are interested I am using Thingspeak to store my data.
     
    So last week I started to look at a way to decode the signals I saw coming in using my spectrum display. Luckily other people had allready done a lot of work on the protocol used by the sensors. The sensordata is send using On/Off keying (OOK).
    See http://ftp.f6fbb.org/domo/sensors/tx_signals.php and http:/ftp.f6fbb.org/domo/sensors/tx3_th.php
     
    After a few days of trial-and-error approach (thanks go to larsie for the feedback and ideas !) I actually was getting signals that could be the sensordata. To cut a long story short, using asynchronous CarrierSense detection on the AIR BOOSTERPACK and timing the length of the pulse coming in I can read the incoming data from several sensors. The software is definitely in its alpha stages. I can read one sensor properly but reading multiple sensors does give problems, if I set the RF registers to read the nearby sensor (3-4 meters away) the far away sensor (>10m) doesnt get picked up. When I set to register to read the far away, the nearby gets picked up but the data isnt as it should be anymore.
     
    Here's an image to show that I get results that are the same as my LaCrosse display shows (from left to right : MSP430 sandwich, Lacrosse display and a not active TX3TX sensor).
     

     
    The code below is based on the same GLCD and TI libraries as I used for my spectrum display project.
     
    regards
    CorB
     
     

    /* * This file is licensed under BSD. The simplicity code is originally copyright Texas Instruments, * but has been adapted by Lars Kristian Roland/Cor Berrevoets * the glcd code is by Lars Kristian Roland/Cor Berrevoets * the tx3th sensor information can be found at http://ftp.f6fbb.org/domo/sensors/tx3_th.php * the sensor first sends temperature information consisting of 11 blocks of 4 bits repeated once * the sensor secondly sends humidity information consisting of 11 blocks of 4 bits repeated once * block 0 is 0000 * block 1 is 1010 (preamble) * block 2 is sensortype 0=temperature E=humidity * block 3 is 4 bits sensorID * block 4 is 3 bits sensorID and another bit (unknown purpose) * block 5/6/7 is temperature in tenths degrees BCD +50 degrees * block 5/6/7 is humidity in tenths percent BCD (always ending at 0) * block 8 = block 6 * block9 = block 7 * block10 = CRC * */ //******************************************************************* // // G2553 // // ----------------- // | | // |VCC GND | // S1/GDO2 |P1.0 P2.6|-RF-GDO0 // S2 |P1.1 P2.7|-RF-CS // SW1 |P1.2 | // LED |P1.3 | // glcd-cs |P1.4 P1.7|<-------| glcd/RF-MISO //glcd/RF-CLK |P1.5 P1.6|------->| glcd/RF-SOMI // S3 |P2.0 P2.5| // S4 |P2.1 P2.4| // |P2.2 P2.3| // | | // ----------------- //******************************************************************* #include "ti/include.h" #include "../library/glcd_charset.c" #include "../library/glcd.c" unsigned long clockcnt=0,lastclock=0; unsigned long lastpulsecnt, pulsecnt=0,faultcount=0, pulselength=0; unsigned char bit; // bitcounter 0..3 unsigned char bitdata[4]={8,4,2,1}; // to create a nibble readout with MSB first coming in char pulseindx; // nibblecounter unsigned char pulsetrain[50],oldpulse[50]; // datapackage storage unsigned char line=4; // display of temperature datapackage int rssi; #define signal BIT2 void setup433MhzOOKreader() { TI_CC_SPIStrobe(TI_CCxxx0_SIDLE); // set IDLE TI_CC_SPIWriteReg(TI_CCxxx0_FREQ2, 0x10); // Freq control word, high byte TI_CC_SPIWriteReg(TI_CCxxx0_FREQ1, 0x00); //Freq control word, mid byte. TI_CC_SPIWriteReg(TI_CCxxx0_FREQ0, 0x00); //Freq control word, low byte. TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG4, 0x06); // RX bandwidth and datarate MSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG3, 0x37); // datarate LSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG2, 0x00); // no preamble/sync TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG1, 0x00); // CHANNEL SPACING and channelspacing MSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG0, 0xe5); // x2E5=200Khz x1E5=100Khz x0E5=50Khz x000=25Khz, CHANNEL SPACING LSB TI_CC_SPIWriteReg(TI_CCxxx0_FOCCFG, 0x00); // no IF compensation for OOK TI_CC_SPIWriteReg(TI_CCxxx0_AGCCTRL2,0xc3); // receiver gain 0xAB A B TI_CC_SPIWriteReg(TI_CCxxx0_PKTCTRL0, 0x32); //asynchronous mode TI_CC_SPIWriteReg(TI_CCxxx0_IOCFG0, 0x0E); //GDO0Output Pin Configuration asynchronous output TI_CC_SPIWriteReg(TI_CCxxx0_CHANNR, 48); // change radio to channel 48 in 432Mhz band (50khz spacing) TI_CC_SPIStrobe(TI_CCxxx0_SRX); // goto receivermode } void main (void) { WDTCTL = WDT_MDLY_0_064; // WDT ~0.064ms interval timer IE1 |= WDTIE; // Enable WDT interrupt P1DIR |=signal; TI_CC_GDO0_PxIES &= ~TI_CC_GDO0_PIN; // Int on falling edge (end of pkt) TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN; // Clear flag for GDO0 TI_CC_GDO0_PxIE |= TI_CC_GDO0_PIN; // Enable interrupt on end of packet RF_init(); // SETUP ANAREN AIR RF __delay_cycles(50000); SPISetup(); // Initialize SPI Display __delay_cycles(100000); clear(); __delay_cycles(100000); //reset the pulsetrain indices and storage arrays for (pulseindx=0; pulseindx<49; pulseindx++) { pulsetrain[pulseindx]=0; oldpulse[pulseindx]=0; } pulsecnt=0; pulseindx=0; bit=0; lastpulsecnt=0; writeInt(0,2,faultcount,3); // display faults writeInt(48,2,pulsecnt,3); // display how many packages have been read setup433MhzOOKreader(); __enable_interrupt(); // enable all interrupts while (1) // do for ever { if (pulsecnt>lastpulsecnt) // display data only of we have received a package { setcharmode(1); // switch to large characters if ((oldpulse[1]==0x0a) && (oldpulse[12]==0x0a)) { unsigned int temperature; unsigned int humidity; temperature=(oldpulse[5]-5)*100+oldpulse[6]*10+oldpulse[7]; writeInt(0,0,temperature,3); humidity=oldpulse[27]*10+oldpulse[28]; writeInt(48,0,humidity,3); lastpulsecnt=pulsecnt; } writeInt(0,2,faultcount,3); // display faults writeInt(48,2,pulsecnt,3); // display how many packages have been read setcharmode(0); // switch to small characters unsigned char temp; char i,x; x=0; // show the 11 nibbles of the temperature part of the package for (i=0; i<11; i++) { temp = oldpulse[i]; temp += (temp > 9) ? 'A' - 10 : '0'; writeChar(x,line,temp); x=x+6; } writeInt(x+6,line,rssi,4); } } } #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // clockcnt++; } #pragma vector=PORT2_VECTOR __interrupt void Port_2(void) { // REALLY cheap debounce. // We can get away with this because we're edge triggering but reading the level. if(TI_CC_GDO0_PxIFG & TI_CC_GDO0_PIN) { pulselength=clockcnt-lastclock; lastclock=clockcnt; if (pulselength<30) {pulsetrain[pulseindx]|=bitdata[bit];} bit++; if (bit==4) {bit=0; pulseindx++;} if (pulseindx>43) // we got all 44 bits in { rssi=TI_CC_SPIReadStatus(TI_CCxxx0_RSSI); __delay_cycles(100); if(rssi < 128) // convert RSSI readout to dB { rssi = -((rssi/2) - 74); } else{ rssi = -(((rssi - 256)/2) - 74); } char j; for (j=0; j<45; j++) {oldpulse[j]=pulsetrain[j]; pulsetrain[j]=0; } //reset indices pulseindx=0; bit=0; //increment the line to display the datapackage line++; if (line>7) {line=4;} if (oldpulse[1]==0x0a) {pulsecnt++;} else {faultcount++; pulsecnt++;} // add a long delay after reading the 44th nibble, corrects possible mistakes also __delay_cycles(10000000); } TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN; // After pkt RX, this flag is set. } }
  2. Like
    CorB got a reaction from Nytblade in MSP430 meets LaCrosse Temperature/Humidity sensor TX3TH   
    Hi,
     
    Excuses for the long post !!
     
    After I found out that I could detect signals in the 433Mhz band using an AIR Boosterpack (See viewtopic.php?f=9&t=2944 AIR Boosterpack RF spectrum display) I wanted to display the data I was receiving on the 433 Mhz band.
    Ive got a Lacrosse temperature/humidity logger WS8610 that can read up to 3 external sensors and log the data. These sensors broadcast their data every minute or so.
     
    Since I have a logger and I have a display you might ask why do you want to read the data ? My motivation for this is simple, the datalogger can only capture data for about 1.5 weeks and then the oldest readings are overwritten and I need to connect the datalogger to an old PC (that still has a USB-DB9 connector) to be able to store the data. If I can read the data directly from the sensors I can hook them up in a system I allready have running with several other sensors (gas, electricityusage, inside temperature) and store the data on the internet. For those that are interested I am using Thingspeak to store my data.
     
    So last week I started to look at a way to decode the signals I saw coming in using my spectrum display. Luckily other people had allready done a lot of work on the protocol used by the sensors. The sensordata is send using On/Off keying (OOK).
    See http://ftp.f6fbb.org/domo/sensors/tx_signals.php and http:/ftp.f6fbb.org/domo/sensors/tx3_th.php
     
    After a few days of trial-and-error approach (thanks go to larsie for the feedback and ideas !) I actually was getting signals that could be the sensordata. To cut a long story short, using asynchronous CarrierSense detection on the AIR BOOSTERPACK and timing the length of the pulse coming in I can read the incoming data from several sensors. The software is definitely in its alpha stages. I can read one sensor properly but reading multiple sensors does give problems, if I set the RF registers to read the nearby sensor (3-4 meters away) the far away sensor (>10m) doesnt get picked up. When I set to register to read the far away, the nearby gets picked up but the data isnt as it should be anymore.
     
    Here's an image to show that I get results that are the same as my LaCrosse display shows (from left to right : MSP430 sandwich, Lacrosse display and a not active TX3TX sensor).
     

     
    The code below is based on the same GLCD and TI libraries as I used for my spectrum display project.
     
    regards
    CorB
     
     

    /* * This file is licensed under BSD. The simplicity code is originally copyright Texas Instruments, * but has been adapted by Lars Kristian Roland/Cor Berrevoets * the glcd code is by Lars Kristian Roland/Cor Berrevoets * the tx3th sensor information can be found at http://ftp.f6fbb.org/domo/sensors/tx3_th.php * the sensor first sends temperature information consisting of 11 blocks of 4 bits repeated once * the sensor secondly sends humidity information consisting of 11 blocks of 4 bits repeated once * block 0 is 0000 * block 1 is 1010 (preamble) * block 2 is sensortype 0=temperature E=humidity * block 3 is 4 bits sensorID * block 4 is 3 bits sensorID and another bit (unknown purpose) * block 5/6/7 is temperature in tenths degrees BCD +50 degrees * block 5/6/7 is humidity in tenths percent BCD (always ending at 0) * block 8 = block 6 * block9 = block 7 * block10 = CRC * */ //******************************************************************* // // G2553 // // ----------------- // | | // |VCC GND | // S1/GDO2 |P1.0 P2.6|-RF-GDO0 // S2 |P1.1 P2.7|-RF-CS // SW1 |P1.2 | // LED |P1.3 | // glcd-cs |P1.4 P1.7|<-------| glcd/RF-MISO //glcd/RF-CLK |P1.5 P1.6|------->| glcd/RF-SOMI // S3 |P2.0 P2.5| // S4 |P2.1 P2.4| // |P2.2 P2.3| // | | // ----------------- //******************************************************************* #include "ti/include.h" #include "../library/glcd_charset.c" #include "../library/glcd.c" unsigned long clockcnt=0,lastclock=0; unsigned long lastpulsecnt, pulsecnt=0,faultcount=0, pulselength=0; unsigned char bit; // bitcounter 0..3 unsigned char bitdata[4]={8,4,2,1}; // to create a nibble readout with MSB first coming in char pulseindx; // nibblecounter unsigned char pulsetrain[50],oldpulse[50]; // datapackage storage unsigned char line=4; // display of temperature datapackage int rssi; #define signal BIT2 void setup433MhzOOKreader() { TI_CC_SPIStrobe(TI_CCxxx0_SIDLE); // set IDLE TI_CC_SPIWriteReg(TI_CCxxx0_FREQ2, 0x10); // Freq control word, high byte TI_CC_SPIWriteReg(TI_CCxxx0_FREQ1, 0x00); //Freq control word, mid byte. TI_CC_SPIWriteReg(TI_CCxxx0_FREQ0, 0x00); //Freq control word, low byte. TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG4, 0x06); // RX bandwidth and datarate MSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG3, 0x37); // datarate LSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG2, 0x00); // no preamble/sync TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG1, 0x00); // CHANNEL SPACING and channelspacing MSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG0, 0xe5); // x2E5=200Khz x1E5=100Khz x0E5=50Khz x000=25Khz, CHANNEL SPACING LSB TI_CC_SPIWriteReg(TI_CCxxx0_FOCCFG, 0x00); // no IF compensation for OOK TI_CC_SPIWriteReg(TI_CCxxx0_AGCCTRL2,0xc3); // receiver gain 0xAB A B TI_CC_SPIWriteReg(TI_CCxxx0_PKTCTRL0, 0x32); //asynchronous mode TI_CC_SPIWriteReg(TI_CCxxx0_IOCFG0, 0x0E); //GDO0Output Pin Configuration asynchronous output TI_CC_SPIWriteReg(TI_CCxxx0_CHANNR, 48); // change radio to channel 48 in 432Mhz band (50khz spacing) TI_CC_SPIStrobe(TI_CCxxx0_SRX); // goto receivermode } void main (void) { WDTCTL = WDT_MDLY_0_064; // WDT ~0.064ms interval timer IE1 |= WDTIE; // Enable WDT interrupt P1DIR |=signal; TI_CC_GDO0_PxIES &= ~TI_CC_GDO0_PIN; // Int on falling edge (end of pkt) TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN; // Clear flag for GDO0 TI_CC_GDO0_PxIE |= TI_CC_GDO0_PIN; // Enable interrupt on end of packet RF_init(); // SETUP ANAREN AIR RF __delay_cycles(50000); SPISetup(); // Initialize SPI Display __delay_cycles(100000); clear(); __delay_cycles(100000); //reset the pulsetrain indices and storage arrays for (pulseindx=0; pulseindx<49; pulseindx++) { pulsetrain[pulseindx]=0; oldpulse[pulseindx]=0; } pulsecnt=0; pulseindx=0; bit=0; lastpulsecnt=0; writeInt(0,2,faultcount,3); // display faults writeInt(48,2,pulsecnt,3); // display how many packages have been read setup433MhzOOKreader(); __enable_interrupt(); // enable all interrupts while (1) // do for ever { if (pulsecnt>lastpulsecnt) // display data only of we have received a package { setcharmode(1); // switch to large characters if ((oldpulse[1]==0x0a) && (oldpulse[12]==0x0a)) { unsigned int temperature; unsigned int humidity; temperature=(oldpulse[5]-5)*100+oldpulse[6]*10+oldpulse[7]; writeInt(0,0,temperature,3); humidity=oldpulse[27]*10+oldpulse[28]; writeInt(48,0,humidity,3); lastpulsecnt=pulsecnt; } writeInt(0,2,faultcount,3); // display faults writeInt(48,2,pulsecnt,3); // display how many packages have been read setcharmode(0); // switch to small characters unsigned char temp; char i,x; x=0; // show the 11 nibbles of the temperature part of the package for (i=0; i<11; i++) { temp = oldpulse[i]; temp += (temp > 9) ? 'A' - 10 : '0'; writeChar(x,line,temp); x=x+6; } writeInt(x+6,line,rssi,4); } } } #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // clockcnt++; } #pragma vector=PORT2_VECTOR __interrupt void Port_2(void) { // REALLY cheap debounce. // We can get away with this because we're edge triggering but reading the level. if(TI_CC_GDO0_PxIFG & TI_CC_GDO0_PIN) { pulselength=clockcnt-lastclock; lastclock=clockcnt; if (pulselength<30) {pulsetrain[pulseindx]|=bitdata[bit];} bit++; if (bit==4) {bit=0; pulseindx++;} if (pulseindx>43) // we got all 44 bits in { rssi=TI_CC_SPIReadStatus(TI_CCxxx0_RSSI); __delay_cycles(100); if(rssi < 128) // convert RSSI readout to dB { rssi = -((rssi/2) - 74); } else{ rssi = -(((rssi - 256)/2) - 74); } char j; for (j=0; j<45; j++) {oldpulse[j]=pulsetrain[j]; pulsetrain[j]=0; } //reset indices pulseindx=0; bit=0; //increment the line to display the datapackage line++; if (line>7) {line=4;} if (oldpulse[1]==0x0a) {pulsecnt++;} else {faultcount++; pulsecnt++;} // add a long delay after reading the 44th nibble, corrects possible mistakes also __delay_cycles(10000000); } TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN; // After pkt RX, this flag is set. } }
  3. Like
    CorB got a reaction from bluehash in MSP430 meets LaCrosse Temperature/Humidity sensor TX3TH   
    Hi,
     
    Excuses for the long post !!
     
    After I found out that I could detect signals in the 433Mhz band using an AIR Boosterpack (See viewtopic.php?f=9&t=2944 AIR Boosterpack RF spectrum display) I wanted to display the data I was receiving on the 433 Mhz band.
    Ive got a Lacrosse temperature/humidity logger WS8610 that can read up to 3 external sensors and log the data. These sensors broadcast their data every minute or so.
     
    Since I have a logger and I have a display you might ask why do you want to read the data ? My motivation for this is simple, the datalogger can only capture data for about 1.5 weeks and then the oldest readings are overwritten and I need to connect the datalogger to an old PC (that still has a USB-DB9 connector) to be able to store the data. If I can read the data directly from the sensors I can hook them up in a system I allready have running with several other sensors (gas, electricityusage, inside temperature) and store the data on the internet. For those that are interested I am using Thingspeak to store my data.
     
    So last week I started to look at a way to decode the signals I saw coming in using my spectrum display. Luckily other people had allready done a lot of work on the protocol used by the sensors. The sensordata is send using On/Off keying (OOK).
    See http://ftp.f6fbb.org/domo/sensors/tx_signals.php and http:/ftp.f6fbb.org/domo/sensors/tx3_th.php
     
    After a few days of trial-and-error approach (thanks go to larsie for the feedback and ideas !) I actually was getting signals that could be the sensordata. To cut a long story short, using asynchronous CarrierSense detection on the AIR BOOSTERPACK and timing the length of the pulse coming in I can read the incoming data from several sensors. The software is definitely in its alpha stages. I can read one sensor properly but reading multiple sensors does give problems, if I set the RF registers to read the nearby sensor (3-4 meters away) the far away sensor (>10m) doesnt get picked up. When I set to register to read the far away, the nearby gets picked up but the data isnt as it should be anymore.
     
    Here's an image to show that I get results that are the same as my LaCrosse display shows (from left to right : MSP430 sandwich, Lacrosse display and a not active TX3TX sensor).
     

     
    The code below is based on the same GLCD and TI libraries as I used for my spectrum display project.
     
    regards
    CorB
     
     

    /* * This file is licensed under BSD. The simplicity code is originally copyright Texas Instruments, * but has been adapted by Lars Kristian Roland/Cor Berrevoets * the glcd code is by Lars Kristian Roland/Cor Berrevoets * the tx3th sensor information can be found at http://ftp.f6fbb.org/domo/sensors/tx3_th.php * the sensor first sends temperature information consisting of 11 blocks of 4 bits repeated once * the sensor secondly sends humidity information consisting of 11 blocks of 4 bits repeated once * block 0 is 0000 * block 1 is 1010 (preamble) * block 2 is sensortype 0=temperature E=humidity * block 3 is 4 bits sensorID * block 4 is 3 bits sensorID and another bit (unknown purpose) * block 5/6/7 is temperature in tenths degrees BCD +50 degrees * block 5/6/7 is humidity in tenths percent BCD (always ending at 0) * block 8 = block 6 * block9 = block 7 * block10 = CRC * */ //******************************************************************* // // G2553 // // ----------------- // | | // |VCC GND | // S1/GDO2 |P1.0 P2.6|-RF-GDO0 // S2 |P1.1 P2.7|-RF-CS // SW1 |P1.2 | // LED |P1.3 | // glcd-cs |P1.4 P1.7|<-------| glcd/RF-MISO //glcd/RF-CLK |P1.5 P1.6|------->| glcd/RF-SOMI // S3 |P2.0 P2.5| // S4 |P2.1 P2.4| // |P2.2 P2.3| // | | // ----------------- //******************************************************************* #include "ti/include.h" #include "../library/glcd_charset.c" #include "../library/glcd.c" unsigned long clockcnt=0,lastclock=0; unsigned long lastpulsecnt, pulsecnt=0,faultcount=0, pulselength=0; unsigned char bit; // bitcounter 0..3 unsigned char bitdata[4]={8,4,2,1}; // to create a nibble readout with MSB first coming in char pulseindx; // nibblecounter unsigned char pulsetrain[50],oldpulse[50]; // datapackage storage unsigned char line=4; // display of temperature datapackage int rssi; #define signal BIT2 void setup433MhzOOKreader() { TI_CC_SPIStrobe(TI_CCxxx0_SIDLE); // set IDLE TI_CC_SPIWriteReg(TI_CCxxx0_FREQ2, 0x10); // Freq control word, high byte TI_CC_SPIWriteReg(TI_CCxxx0_FREQ1, 0x00); //Freq control word, mid byte. TI_CC_SPIWriteReg(TI_CCxxx0_FREQ0, 0x00); //Freq control word, low byte. TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG4, 0x06); // RX bandwidth and datarate MSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG3, 0x37); // datarate LSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG2, 0x00); // no preamble/sync TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG1, 0x00); // CHANNEL SPACING and channelspacing MSB TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG0, 0xe5); // x2E5=200Khz x1E5=100Khz x0E5=50Khz x000=25Khz, CHANNEL SPACING LSB TI_CC_SPIWriteReg(TI_CCxxx0_FOCCFG, 0x00); // no IF compensation for OOK TI_CC_SPIWriteReg(TI_CCxxx0_AGCCTRL2,0xc3); // receiver gain 0xAB A B TI_CC_SPIWriteReg(TI_CCxxx0_PKTCTRL0, 0x32); //asynchronous mode TI_CC_SPIWriteReg(TI_CCxxx0_IOCFG0, 0x0E); //GDO0Output Pin Configuration asynchronous output TI_CC_SPIWriteReg(TI_CCxxx0_CHANNR, 48); // change radio to channel 48 in 432Mhz band (50khz spacing) TI_CC_SPIStrobe(TI_CCxxx0_SRX); // goto receivermode } void main (void) { WDTCTL = WDT_MDLY_0_064; // WDT ~0.064ms interval timer IE1 |= WDTIE; // Enable WDT interrupt P1DIR |=signal; TI_CC_GDO0_PxIES &= ~TI_CC_GDO0_PIN; // Int on falling edge (end of pkt) TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN; // Clear flag for GDO0 TI_CC_GDO0_PxIE |= TI_CC_GDO0_PIN; // Enable interrupt on end of packet RF_init(); // SETUP ANAREN AIR RF __delay_cycles(50000); SPISetup(); // Initialize SPI Display __delay_cycles(100000); clear(); __delay_cycles(100000); //reset the pulsetrain indices and storage arrays for (pulseindx=0; pulseindx<49; pulseindx++) { pulsetrain[pulseindx]=0; oldpulse[pulseindx]=0; } pulsecnt=0; pulseindx=0; bit=0; lastpulsecnt=0; writeInt(0,2,faultcount,3); // display faults writeInt(48,2,pulsecnt,3); // display how many packages have been read setup433MhzOOKreader(); __enable_interrupt(); // enable all interrupts while (1) // do for ever { if (pulsecnt>lastpulsecnt) // display data only of we have received a package { setcharmode(1); // switch to large characters if ((oldpulse[1]==0x0a) && (oldpulse[12]==0x0a)) { unsigned int temperature; unsigned int humidity; temperature=(oldpulse[5]-5)*100+oldpulse[6]*10+oldpulse[7]; writeInt(0,0,temperature,3); humidity=oldpulse[27]*10+oldpulse[28]; writeInt(48,0,humidity,3); lastpulsecnt=pulsecnt; } writeInt(0,2,faultcount,3); // display faults writeInt(48,2,pulsecnt,3); // display how many packages have been read setcharmode(0); // switch to small characters unsigned char temp; char i,x; x=0; // show the 11 nibbles of the temperature part of the package for (i=0; i<11; i++) { temp = oldpulse[i]; temp += (temp > 9) ? 'A' - 10 : '0'; writeChar(x,line,temp); x=x+6; } writeInt(x+6,line,rssi,4); } } } #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // clockcnt++; } #pragma vector=PORT2_VECTOR __interrupt void Port_2(void) { // REALLY cheap debounce. // We can get away with this because we're edge triggering but reading the level. if(TI_CC_GDO0_PxIFG & TI_CC_GDO0_PIN) { pulselength=clockcnt-lastclock; lastclock=clockcnt; if (pulselength<30) {pulsetrain[pulseindx]|=bitdata[bit];} bit++; if (bit==4) {bit=0; pulseindx++;} if (pulseindx>43) // we got all 44 bits in { rssi=TI_CC_SPIReadStatus(TI_CCxxx0_RSSI); __delay_cycles(100); if(rssi < 128) // convert RSSI readout to dB { rssi = -((rssi/2) - 74); } else{ rssi = -(((rssi - 256)/2) - 74); } char j; for (j=0; j<45; j++) {oldpulse[j]=pulsetrain[j]; pulsetrain[j]=0; } //reset indices pulseindx=0; bit=0; //increment the line to display the datapackage line++; if (line>7) {line=4;} if (oldpulse[1]==0x0a) {pulsecnt++;} else {faultcount++; pulsecnt++;} // add a long delay after reading the 44th nibble, corrects possible mistakes also __delay_cycles(10000000); } TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN; // After pkt RX, this flag is set. } }
  4. Like
    CorB reacted to oPossum in Volt/Amp/Watt meter   
    This is a simple voltage and current meter that uses the TI INA219 chip. Voltage measurement range is 0 to 26 volts with 4 mV resolution and current measurement range is -4 to +4 amps with 1 mV resolution (when using a 0.01 ohm shunt). The specs are inferior to a pair of quality multimeters, but it is a fraction of the price and shows wattage in addition to voltage and current. The Nokia 5110 display is used so the firmware could be enhanced to do simple graphing. Sending the measurements to a computer could also be done.
     
    Using the INA219 makes for a very simple circuit.

     
    The normal display is three lines with voltage, amperage and wattage.

     
    Pressing the P1.3 switch will show the 6 registers in the INA219 in hex and signed decimal.

     
    The code is written in C++ and uses templates for the LCD, IIC and INA219. Software SPI and IIC is used for maximum portability.
    vam.zip
  5. Like
    CorB reacted to RobG in MSP430F5510 USB Development Board   
    MSP430F5510 development board, inspired by xpg, with LaunchPad compatible headers.
     




  6. Like
    CorB reacted to larsie in AIR Boosterpack RF spectrum display   
    Cool project. Thanks
     
    For OOK you may be able to look at the Carrier Sense and define CS as an output on the output pin of the Cc1101. There is also a separate mode for the cc1101 that turns off packet control (synchronous mode??? ) which is used for this sort of thing. The cc1101 is designed as a very flexible chip to replace old tech implementations for sensors, garage openers etc.
     
    There is an ook mode also, and you can use smartrf studio to get the right parameters. Then the first powerlevel configs are used to say if it shiuld be ask or ook. But in this case you need to know the bitrate, and the protocol needs to have same length of on and off bits. Many of the protocols use length of the pulse to indicate low and high, which makes CS a good option I think.
  7. Like
    CorB got a reaction from dacoffey in AIR Boosterpack RF spectrum display   
    Hi all,
     
    One of the things I wanted to build using the Anaren AIR boosterpack was a mini spectrum "analyzer" or spectrum display. During my holiday i found time to play around with both the AIR boosterpack and the LCD module Lars has produced.
     
    Although the AIR boosterpack was designed for 868/915 Mhz it seems the receiver inside (CC110L) is sensitive also in the 433Mhz region. The code I share with this mail allows the user (by changing a define) to switch between 3 frequencybands. Two buttons of the LCD package allow change of RX bandwidth and channelwidth.
     
    THe screenshot below shows a typical readout in the 433 Mhz band in a room where a Lacross TX3TH temperature/humidity sensor is sending data every minute using an OOK protocol (Request: if anybody knows how to receive/decode OOK using a CC110L please inform me). The display shows the low and high frequency in Mhz and shows the frequency with the highest readout (RSSI in dB) in kHz and as a blinking line in the graph.
     

     
    If you want to know more about this mini spectrum display or have other comments, feel free to share them.
     
    regards
    CorB
    spectrum.zip
    glcd.zip
  8. Like
    CorB got a reaction from Automate in AIR Boosterpack RF spectrum display   
    Hi all,
     
    One of the things I wanted to build using the Anaren AIR boosterpack was a mini spectrum "analyzer" or spectrum display. During my holiday i found time to play around with both the AIR boosterpack and the LCD module Lars has produced.
     
    Although the AIR boosterpack was designed for 868/915 Mhz it seems the receiver inside (CC110L) is sensitive also in the 433Mhz region. The code I share with this mail allows the user (by changing a define) to switch between 3 frequencybands. Two buttons of the LCD package allow change of RX bandwidth and channelwidth.
     
    THe screenshot below shows a typical readout in the 433 Mhz band in a room where a Lacross TX3TH temperature/humidity sensor is sending data every minute using an OOK protocol (Request: if anybody knows how to receive/decode OOK using a CC110L please inform me). The display shows the low and high frequency in Mhz and shows the frequency with the highest readout (RSSI in dB) in kHz and as a blinking line in the graph.
     

     
    If you want to know more about this mini spectrum display or have other comments, feel free to share them.
     
    regards
    CorB
    spectrum.zip
    glcd.zip
  9. Like
    CorB got a reaction from Nytblade in AIR Boosterpack RF spectrum display   
    Hi all,
     
    One of the things I wanted to build using the Anaren AIR boosterpack was a mini spectrum "analyzer" or spectrum display. During my holiday i found time to play around with both the AIR boosterpack and the LCD module Lars has produced.
     
    Although the AIR boosterpack was designed for 868/915 Mhz it seems the receiver inside (CC110L) is sensitive also in the 433Mhz region. The code I share with this mail allows the user (by changing a define) to switch between 3 frequencybands. Two buttons of the LCD package allow change of RX bandwidth and channelwidth.
     
    THe screenshot below shows a typical readout in the 433 Mhz band in a room where a Lacross TX3TH temperature/humidity sensor is sending data every minute using an OOK protocol (Request: if anybody knows how to receive/decode OOK using a CC110L please inform me). The display shows the low and high frequency in Mhz and shows the frequency with the highest readout (RSSI in dB) in kHz and as a blinking line in the graph.
     

     
    If you want to know more about this mini spectrum display or have other comments, feel free to share them.
     
    regards
    CorB
    spectrum.zip
    glcd.zip
  10. Like
    CorB got a reaction from bluehash in AIR Boosterpack RF spectrum display   
    Hi all,
     
    One of the things I wanted to build using the Anaren AIR boosterpack was a mini spectrum "analyzer" or spectrum display. During my holiday i found time to play around with both the AIR boosterpack and the LCD module Lars has produced.
     
    Although the AIR boosterpack was designed for 868/915 Mhz it seems the receiver inside (CC110L) is sensitive also in the 433Mhz region. The code I share with this mail allows the user (by changing a define) to switch between 3 frequencybands. Two buttons of the LCD package allow change of RX bandwidth and channelwidth.
     
    THe screenshot below shows a typical readout in the 433 Mhz band in a room where a Lacross TX3TH temperature/humidity sensor is sending data every minute using an OOK protocol (Request: if anybody knows how to receive/decode OOK using a CC110L please inform me). The display shows the low and high frequency in Mhz and shows the frequency with the highest readout (RSSI in dB) in kHz and as a blinking line in the graph.
     

     
    If you want to know more about this mini spectrum display or have other comments, feel free to share them.
     
    regards
    CorB
    spectrum.zip
    glcd.zip
  11. Like
    CorB got a reaction from RobG in AIR Boosterpack RF spectrum display   
    Hi all,
     
    One of the things I wanted to build using the Anaren AIR boosterpack was a mini spectrum "analyzer" or spectrum display. During my holiday i found time to play around with both the AIR boosterpack and the LCD module Lars has produced.
     
    Although the AIR boosterpack was designed for 868/915 Mhz it seems the receiver inside (CC110L) is sensitive also in the 433Mhz region. The code I share with this mail allows the user (by changing a define) to switch between 3 frequencybands. Two buttons of the LCD package allow change of RX bandwidth and channelwidth.
     
    THe screenshot below shows a typical readout in the 433 Mhz band in a room where a Lacross TX3TH temperature/humidity sensor is sending data every minute using an OOK protocol (Request: if anybody knows how to receive/decode OOK using a CC110L please inform me). The display shows the low and high frequency in Mhz and shows the frequency with the highest readout (RSSI in dB) in kHz and as a blinking line in the graph.
     

     
    If you want to know more about this mini spectrum display or have other comments, feel free to share them.
     
    regards
    CorB
    spectrum.zip
    glcd.zip
  12. Like
    CorB got a reaction from bluehash in Motion detection using MSP430g2131   
    Hi,
     
    Below is the code I have been using without problems (btw the source isnt mine, see http://www.43oh.com/2010/09/interface-t ... ir-sensor/)
     
    regards
    CorB
     

    // LaunchPad PIR Sensor test // Interfaces a Parallax PIR sensor with the LaunchPad // When the PIR senses movement, LED1 will be on for ~2s, then off // LED2 is always on // initially written by suspended-chord/gatesphere (http://suspended-chord.info/) // released into the public domain #include #define PIRsensor BIT4 void main() { WDTCTL = WDTPW + WDTHOLD; // kill wdt P1DIR = BIT0 + BIT6+BIT3; // set LED1 and LED2 to OUT P1OUT = BIT6; // LED2 always on - indicates power P1REN = PIRsensor; //enable internal pullup/down P1OUT |= PIRsensor; //select pullup P1IES &= ~PIRsensor; // low-high edge initially P1IFG &= ~PIRsensor; // prevent immediate interrupt P1IE |= PIRsensor; // enable interrupts on P1.4 alarm(); _BIS_SR(LPM3_bits + GIE); // enable GPIO interrupts and send into LPM4 //for (;; // loop forever } // interrupt for P1 #pragma vector = PORT1_VECTOR __interrupt void P1_ISR() { if ((P1IFG & PIRsensor) == PIRsensor) { // if motion sensed P1IFG &= ~PIRsensor; // clear interrupt flag P1OUT ^= BIT0; // toggle LED1 P1IES ^= PIRsensor; // toggle edge } else { P1IFG = 0; // clear all other flags to prevent infinite interrupt loops } }
  13. Like
    CorB reacted to voodoofish in Data Logger board   
    This is the first graph of data pulled from the data logger. This was a simple test, but verified saving and retrieving of data from the chip and some other test functions that I have been working on. This test used the WDT interval timer and took roughly an hour to run to collect 4096 samples. The variances in temp were due to the time and the amount of sun hitting the logger(2 rapid increases in temp). I think it's time to populate another board as I know the setup works and would allow me to start running longer tests while working on code.

  14. Like
    CorB got a reaction from jaeger92 in Anaren TI CC110L RF AIR Booster Pack   
    Hi,
     
    You have many free pins, on a G2553 P1.4 - P1.7 are used for SPI communcation with the boosterpack and pin 2.6/2.7 are also in use by the boosterpack. So you have P1.0-P1.3 and P2.0-2.5 to be used for your demands.
     
    regards
    CorB
  15. Like
    CorB got a reaction from xv4y in Default clock for a MSP430G2553 (LaunchPad)   
    Hi,
     
    You might have a look into this:
    http://electronics.stackexchange.com/qu ... ld-weather
     
    The DCO is rather sensitive for temperature changes.
     
    cheers
     
    CorB
  16. Like
    CorB got a reaction from Tribes in LCD and Touch booster pack   
    Hi,
     
    After getting in contact with Larsie I managed to buy one of these modules. I went for the non-touch version since it has a space to mount an MSP chip on a DIP socket, bind that to an Anaren AIR module and you have a neat small package. Better than my current setup where I am using a 16x2 LCD to display the info that goes around in my wireless test-system.
     
    The board arrived swift - not so odd as Norway isnt that far away from the Netherlands - and I got it up and running rather fast. It was easy to use the LCD and the Anaren AIR module together, no needs to configure anything special. Rewriting the old LCD-code to the new SPI-driven setup was easy. Larsie also helped me out connecting the backlight.
     
    Here's how the module looks after installing and creating some code to see the output of the wireless nodes. I even managed to get a graph of one of the nodes that displays the change of its readout. And yep ... no buttons installed yet.

     
    One thing however isnt optimal yet, when the LCD is positioned normally (so you can read it easy) the Anaren AIR module is positioned sideways and the antenna isnt oriented optimally. Next step I am currently working on is using a rotated font and the first steps into that seem to be going in the right direction.
     

     
    Its a nice small display that can be helpfull during development allowing you to have both text and graphics (albeit limited !) on a screen. I am happy Larsie made this and that I am able to use this.
     
    cheers
    Cor
  17. Like
    CorB got a reaction from RobG in LCD and Touch booster pack   
    Hi,
     
    After getting in contact with Larsie I managed to buy one of these modules. I went for the non-touch version since it has a space to mount an MSP chip on a DIP socket, bind that to an Anaren AIR module and you have a neat small package. Better than my current setup where I am using a 16x2 LCD to display the info that goes around in my wireless test-system.
     
    The board arrived swift - not so odd as Norway isnt that far away from the Netherlands - and I got it up and running rather fast. It was easy to use the LCD and the Anaren AIR module together, no needs to configure anything special. Rewriting the old LCD-code to the new SPI-driven setup was easy. Larsie also helped me out connecting the backlight.
     
    Here's how the module looks after installing and creating some code to see the output of the wireless nodes. I even managed to get a graph of one of the nodes that displays the change of its readout. And yep ... no buttons installed yet.

     
    One thing however isnt optimal yet, when the LCD is positioned normally (so you can read it easy) the Anaren AIR module is positioned sideways and the antenna isnt oriented optimally. Next step I am currently working on is using a rotated font and the first steps into that seem to be going in the right direction.
     

     
    Its a nice small display that can be helpfull during development allowing you to have both text and graphics (albeit limited !) on a screen. I am happy Larsie made this and that I am able to use this.
     
    cheers
    Cor
  18. Like
    CorB got a reaction from cubeberg in LCD and Touch booster pack   
    Hi,
     
    After getting in contact with Larsie I managed to buy one of these modules. I went for the non-touch version since it has a space to mount an MSP chip on a DIP socket, bind that to an Anaren AIR module and you have a neat small package. Better than my current setup where I am using a 16x2 LCD to display the info that goes around in my wireless test-system.
     
    The board arrived swift - not so odd as Norway isnt that far away from the Netherlands - and I got it up and running rather fast. It was easy to use the LCD and the Anaren AIR module together, no needs to configure anything special. Rewriting the old LCD-code to the new SPI-driven setup was easy. Larsie also helped me out connecting the backlight.
     
    Here's how the module looks after installing and creating some code to see the output of the wireless nodes. I even managed to get a graph of one of the nodes that displays the change of its readout. And yep ... no buttons installed yet.

     
    One thing however isnt optimal yet, when the LCD is positioned normally (so you can read it easy) the Anaren AIR module is positioned sideways and the antenna isnt oriented optimally. Next step I am currently working on is using a rotated font and the first steps into that seem to be going in the right direction.
     

     
    Its a nice small display that can be helpfull during development allowing you to have both text and graphics (albeit limited !) on a screen. I am happy Larsie made this and that I am able to use this.
     
    cheers
    Cor
  19. Like
    CorB got a reaction from bluehash in LCD and Touch booster pack   
    Hi,
     
    After getting in contact with Larsie I managed to buy one of these modules. I went for the non-touch version since it has a space to mount an MSP chip on a DIP socket, bind that to an Anaren AIR module and you have a neat small package. Better than my current setup where I am using a 16x2 LCD to display the info that goes around in my wireless test-system.
     
    The board arrived swift - not so odd as Norway isnt that far away from the Netherlands - and I got it up and running rather fast. It was easy to use the LCD and the Anaren AIR module together, no needs to configure anything special. Rewriting the old LCD-code to the new SPI-driven setup was easy. Larsie also helped me out connecting the backlight.
     
    Here's how the module looks after installing and creating some code to see the output of the wireless nodes. I even managed to get a graph of one of the nodes that displays the change of its readout. And yep ... no buttons installed yet.

     
    One thing however isnt optimal yet, when the LCD is positioned normally (so you can read it easy) the Anaren AIR module is positioned sideways and the antenna isnt oriented optimally. Next step I am currently working on is using a rotated font and the first steps into that seem to be going in the right direction.
     

     
    Its a nice small display that can be helpfull during development allowing you to have both text and graphics (albeit limited !) on a screen. I am happy Larsie made this and that I am able to use this.
     
    cheers
    Cor
  20. Like
    CorB got a reaction from larsie in LCD and Touch booster pack   
    Hi,
     
    After getting in contact with Larsie I managed to buy one of these modules. I went for the non-touch version since it has a space to mount an MSP chip on a DIP socket, bind that to an Anaren AIR module and you have a neat small package. Better than my current setup where I am using a 16x2 LCD to display the info that goes around in my wireless test-system.
     
    The board arrived swift - not so odd as Norway isnt that far away from the Netherlands - and I got it up and running rather fast. It was easy to use the LCD and the Anaren AIR module together, no needs to configure anything special. Rewriting the old LCD-code to the new SPI-driven setup was easy. Larsie also helped me out connecting the backlight.
     
    Here's how the module looks after installing and creating some code to see the output of the wireless nodes. I even managed to get a graph of one of the nodes that displays the change of its readout. And yep ... no buttons installed yet.

     
    One thing however isnt optimal yet, when the LCD is positioned normally (so you can read it easy) the Anaren AIR module is positioned sideways and the antenna isnt oriented optimally. Next step I am currently working on is using a rotated font and the first steps into that seem to be going in the right direction.
     

     
    Its a nice small display that can be helpfull during development allowing you to have both text and graphics (albeit limited !) on a screen. I am happy Larsie made this and that I am able to use this.
     
    cheers
    Cor
  21. Like
    CorB got a reaction from bluehash in Sending long int using simpliciTI   
    Hi Kasper,
     
    I send my data using a structure , see below how my current structure is set up.
     
    typedef volatile struct StatusStruct{
    enum TxACKMessageType { //!< Flags to ACK transfer
    REQUEST_NO_ACK = 0,
    REQUEST_ACK = 1
    } TxACKMessageType;
     
    enum RxACKMessageType { //!< Flags to ACK transfer
    RECEIVED_NO_ACK = 0,
    RECEIVED_ACK = 1
    } RxACKMessageType;
     
    char channel;
    char power;
    char RSSI;
    unsigned int msgNodeId;
    } StatusStruct;
     
    typedef struct PayloadFrame {
     
    char addr; // payloads need to start with char addr as the receiver can check this !
    char msg; // messagetype 0x00 - 0xFF options
    char msgdata0; // var1 that belongs to the message
    char msgdata1; // var2 that belongs to the message
    StatusStruct Status;
     
    // USER DESIGNED PAYLOAD SECTION
    unsigned int data1;
    //unsigned int data2;
    char DataUnit;
     
    } PayloadFrame;
     
    I then load the structure in a txbuffer array and replace the 0 byte of the txbuffer with the actual size of the structure leaving flexibility.
     
    // load a payload into the TxBuffer
    char PreparetxBuffer (char *payload, char len)
    {
    int i = 0;
    for (i = len; i >= 0; i--)
    { txBuffer[i+1] = payload; // Create DataPacket from Payload
    }
    txBuffer[0]=len; // byte 0 in the pack should be the package length
    return 0;
    }
     
    And finally I send in this fashion (Out_Payload is my default variable for sending data);
     
    // Send a payload
    void send_Msg(char message)
    {
    Out_Payload.addr=0x01;//force address
    Out_Payload.msg=message;
    PreparetxBuffer( (char *)(MakeTxPayload()), sizeof(PayloadFrame));
    RFSendPacket(txBuffer, txBuffer[0]+1);
    __delay_cycles(5000); //5ms waiting
    }
     
    Notice that I use another routine called MakeTxPayload to get the data available within PreparetxBuffer, probably due to my limited knowledge of C. Here's the routine:
     
    // transfer of a payload
    PayloadFrame * MakeTxPayload ()
    { Out_Payload.Status.msgNodeId=NodeId; // always enforce !
    return &Out_Payload;
    }
     
    cheers
    Cor
  22. Like
    CorB reacted to oPossum in Software async serial tx/rx without timer   
    Had some requests for this in IRC so here it is. This is an improved version of the serial tx previously posted and new serial rx code. Both tx and rx are blocking and interrupts should be disabled before calling.
     
    C code to show how to use the serial_setup(), putc(), puts(), and getc() functions.
    This will receive a character, increment it and echo it back. So if you type 'A', then 'B' will be echoed.

    // test.c #include "msp430g2211.h" // Functions in serial.asm (this really should be in a header file) void serial_setup(unsigned out_mask, unsigned in_mask, unsigned duration); void putc(unsigned); void puts(char *); unsigned getc(void); void main(void) { char c; // Disable watchdog WDTCTL = WDTPW + WDTHOLD; // Use 1 MHz DCO factory calibration DCOCTL = 0; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; // Setup the serial port // Serial out: P1.1 (BIT1) // Serial in: P1.2 (BIT2) // Bit rate: 9600 (CPU freq / bit rate) serial_setup(BIT1, BIT2, 1000000 / 9600); // Send a string puts("\r\nRunning...\r\n"); for(; { // Do forever c = getc(); // Get a char ++c; // Increment it putc(c); // Echo it back } }
     
    The serial tx/rx code. Just add this as a new source file in your CCS project and it will be callable from your C code.

    ; serial.asm .cdecls C, LIST, "msp430g2231.h" .bss in_bit_mask, 2 ; Serial in pin .bss out_bit_mask, 2 ; Serial out pin .bss bit_dur, 2 ; Bit duration in cycles .bss half_dur, 2 ; Half bit duration in cycles ; .text ; .def serial_setup ; void serial_setup(unsigned out_mask, unsigned in_mask, unsigned bit_duration); .def putc ; void putc(unsigned c); .def puts ; void puts(char *s); .def getc ; unsigned getc(void); ; ; serial_setup ; - Setup serial I/O bitmasks and bit duration (32 minimum) mov R12, &out_bit_mask ; Save serial output bitmask mov R13, &in_bit_mask ; Save serial input bitmask bis.b R12, &P1DIR ; Setup output pin bis.b R12, &P1OUT ; bic.b R13, &P1DIR ; Setup input pin or R13, R12 ; bic.b R12, &P1SEL ; Setup peripheral select mov R14, R12 ; sub #16, R14 ; Adjust count for loop overhead rla R14 ; Multiply by 2 because NOP is two bytes mov R14, &bit_dur ; Save bit duration sub #32, R12 ; Adjust count for loop overhead mov R12, &half_dur ; Save half bit duration ret ; Return ; ; - Send a single char putc ; Char to tx in R12 ; R12, R13, R14, R15 trashed mov &out_bit_mask, R15 ; Serial output bitmask mov &bit_dur, R14 ; Bit duration or #0x0300, R12 ; Stop bit(s) jmp bit_low ; Send start bit... ; tx_bit mov R14, R13 ; Get bit duration tx_delay nop ; 4 cycle loop sub #8, R13 ; jc tx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; rra R12 ; Get bit to tx, test for zero jc bit_high ; If high... bit_low bic.b R15, &P1OUT ; Send zero bit jmp tx_bit ; Next bit... bit_high bis.b R15, &P1OUT ; Send one bit jnz tx_bit ; If tx data is not zero, then there are more bits to send... ; ret ; Return when all bits sent ; ; ; - Send a NULL terminated string puts ; Tx string using putc push R11 ; mov R12, R11 ; String pointer in R12, copy to R11 putsloop ; mov.b @R11+, R12 ; Get a byte, inc pointer tst.b R12 ; Test if end of string jz putsx ; Yes, exit... call #putc ; Call putc jmp putsloop ; putsx pop R11 ; ret ; ; getc ; - Get a char mov &bit_dur, R14 ; Bit duration mov &in_bit_mask, R13 ; Input bitmask mov #0x01FF, R12 ; 9 bits - 8 data + stop ; rx_start ; Wait for start bit mov.b &P1IN, R15 ; Get serial input and R13, R15 ; Mask and test bit jc rx_start ; Wait for low... ; mov &half_dur, R13 ; Wait for 1/2 bit time ; rx_delay nop ; Bit delay sub #8, R13 ; jc rx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; mov.b &P1IN, R15 ; Get serial input and &in_bit_mask, R15 ; rrc R12 ; Shift in a bit ; mov R14, R13 ; Setup bit timer jc rx_delay ; Next bit... ; rla R12 ; Move stop bit to carry swpb R12 ; Move rx byte to lower byte, start bit in msb ret ; Return with rx char and start bit in R12, stop bit in carry ; .end ;
  23. Like
    CorB reacted to larsie in LCD and Touch booster pack   
    I have now made three LCD boosterpacks for the MSP430 Launchpad or other 3V microcontrollers. These are based on the Powertip PE9665WRF display with the ST7579 controller. The screen is small (28x19mm viewable area) and requires little power (0.2mA). It is SPI-based, has backlight and has 96x65 dots. It's a perfect display if you need a cheap, small and low-power display for your next project. If you want to make your own boosterpack, I can also sell the display itself. I have bought a bunch of 250 displays, so need to get rid of them. I won't be making any money on these boosterpack. I'm doing it for fun and learning. They will cost more than SA's booster pack though.
     
    The boosterpacks are currently in their first version, and may evolve and be improved from this description. The packs are:
     

    [*:2qc5g0f6]- LCD Touch Boosterpack - a classic boosterpack with the LCD and 4
  24. Like
    CorB got a reaction from speedsthatbeat in Anaren TI CC110L RF AIR Booster Pack   
    Hi,
     
    Here's a snippet of the code I am using to send packages around:
     
    typedef volatile struct StatusStruct{
    enum TxACKMessageType { //!< Flags to ACK transfer
    REQUEST_NO_ACK = 0,
    REQUEST_ACK = 1
    } TxACKMessageType;
     
    enum RxACKMessageType { //!< Flags to ACK transfer
    RECEIVED_NO_ACK = 0,
    RECEIVED_ACK = 1
    } RxACKMessageType;
     
    char channel;
    char power;
    char RSSI;
    unsigned int msgNodeId;
    } StatusStruct;
     
     
    typedef struct PayloadFrame {
     
    char addr; // payloads need to start with char addr as the receiver can check this !
    char msg; // messagetype 0x00 - 0xFF options
    char msgdata0; // var1 that belongs to the message
    char msgdata1; // var2 that belongs to the message
    StatusStruct Status;
     
    // USER DESIGNED PAYLOAD SECTION
    unsigned int data1;
    char DataUnit;
     
    } PayloadFrame;
     
    The advantage of using a structure is
    a) flexibility
    easy of use all the transforms are internal
     
    Ive just this week tested the same setup using a TI Chronos Watch and can now also communicate between watch and the network of Anaren AIR boosterpacks.
     
    regards
     
    Cor
  25. Like
    CorB reacted to oPossum in Using the internal temperature sensor   
    TI has some sample code for the internal temperature sensor, but it does not explain how to scale the ADC reading to useful units of degrees. Here is a step-by-step explanation of how to do the scaling with integer math for degrees C, K and F. There is also sample code to display the temperature on a Nokia 5110 LCD.

     
    The data sheet (SLAU144) has this formula for converting temperature in degrees Celsius to voltage.
    V = 0.00355 * C + 0.986

    What we need is a formula for converting voltage to temperature.
     
    Rewrite the data sheet fomula with temperature on the left
    0.00355 * C + 0.986 = V
     
    Divide both sides by 0.00355
    C + 277.75 = V / 0.00355
     
    Subtract 277.75 from both sides
    C = V / 0.00355 - 277.75
     
    Now we have a formula for converting voltage to temperature.
     
    The data sheet has this formula for converting voltage to ADC value, once again the opposite of what we neeed.

    For Vref- == 0
    A = 1023 * V / Vref
     
    Swap sides
    1023 * V / Vref = A
     
    Multiply by Vref
    1023 * V = A * Vref
     
    Divide by 1023
    V = A * Vref / 1023
     
    For a 1.5V reference
    V = A * 1.5 / 1023
     
    Simplify
    V = A * 0.0014663
     
    Substitute ADC conversion forumula for voltage in the temperature conversion formula.
    C = A * 0.0014663 / 0.00355 - 277.75
     
    Simplify
    C = A * 0.413 - 277.75
     
    Now we have a formula to convert ADC reading to temperature.
    It uses real numbers, so floating point math is required for good precision.
    Floating point is slow and requires more flash, so let's use integer math instead.
    Multiply by 65536 (2^16) and then divide by the same.
    C = (A * 27069 - 18202393) / 65536
     
    Use a right shift instead of divide. This will become a move of high word to low word.
    C = (A * 27069 - 18202393) >> 16
     
    Add 0.5 * 65536 to impove rounding.
    C = (A * 27069 - 18202393 + 32768) >> 16
     
    Simplify.
    C = (A * 27069 - 18169625) >> 16
     
    So that is how to go from ADC to degrees Celsius.
     
     
    To convert degrees C to degees K.
    K = C + 273.15
     
    Applied to ADC to degrees C conversion formula.
    K = (A * 27069 - 18169625) >> 16 - 273.15
     
    Implement with integer math by multiplying by 65536
    K = (A * 27069 - 18169625 - 17,901,158) >> 16
     
    Simplify.
    K = (A * 27069 - 268467) >> 16
     
    To convert degrees C to degrees F.
    F = C * 9 / 5 + 32
     
    Applied to voltage to degrees C conversion forumula
    F = (V / 0.00355 - 277.75) * 9 / 5 + 32
     
    Multiply by 9
    F = (V / 0.0003944 - 2499.75) / 5 + 32
     
    Divide by 5
    F = (V / 0.0019722 - 499.95) + 32
     
    Add 32
    F = V / 0.0019722 - 467.95
     
    Substitute ADC to voltage forumula
    F = A * 0.0014663 / 0.0019722 - 467.95
     
    Simplifiy
    F = A * 0.7435 - 467.95
     
    Convert to integer
    F = (A * 48724 - 30667156) >> 16
     
    Improve rounding
    F = (A * 48724 - 30667156 + 32768) >> 16
     
    Simplify
    F = (A * 48724 - 30634388) >> 16
     
    So now we have three formulas to convert ADC reading to degrees C, K and F using fast and compact integer math.
    C = (A * 27069 - 18169625) >> 16
    K = (A * 27069 - 268467) >> 16
    F = (A * 48724 - 30634388) >> 16
     
    Using the ADC value, rather than a different temperature scale, will ensure greatest precision for each temperature scale.
     
    main.c

    #include #include #include "lcd.h" #define ADC_SLEEP // Sleep during ADC conversion //#define SHOW_ADC // Show ADC raw and ADC millivolts // Print integer from -999 to 9999 using 12 x 16 font void print_int(int i, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; unsigned x = 48; do { d = div(d.quot, 10); pd12(d.rem, x -= 12, y); } while(d.quot); if(neg) pd12(14, x -= 12, y); while(x) pd12(10, x -= 12, y); } // Print integer from 0 to 9999 vertically using 6 x 8 font void print_v(int i, unsigned x) { unsigned y = 4; unsigned c; if(i < 0 || i > 9999) return; div_t d; d.quot = i; do { d = div(d.quot, 10); c = d.rem + '0'; lcd_print((char *)&c, x, --y); } while(d.quot); c = ' '; while(y) lcd_print((char *)&c, x, --y); } void main(void) { unsigned adc; // ADC value int c, k, f; // Temperature in degrees C, K, and F unsigned mv; // ADC reading in millivolts // WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset // lcd_init(); // Initialize LCD lcd_clear(0); // pd12(15, 48, 0); // Degrees pd12(17, 59, 0); // F pd12(15, 48, 2); // Degrees pd12(16, 58, 2); // C pd12(15, 48, 4); // Degrees pd12(18, 59, 4); // K #ifdef SHOW_ADC // lcd_print("Am", 72, 4); // AD / mV lcd_print("DV", 72, 5); // #endif // // ADC10CTL0 = 0; // Configure ADC ADC10CTL1 = INCH_10 | ADC10DIV_3; // ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE; //ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE | REF2_5V; #ifdef ADC_SLEEP // ADC10CTL0 |= ADC10IE; // Enable ADC conversion complete interrupt #endif // // for(; { // for-ever #ifdef ADC_SLEEP // ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion __bis_SR_register(LPM0_bits + GIE); // Sleep until conversion complete #else // ADC10CTL0 &= ~ADC10IFG; // Clear conversion complete flag ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion while(!(ADC10CTL0 & ADC10IFG)); // Wait for conversion to complete #endif // // adc = ADC10MEM; // Read ADC // // Convert to temperature c = ((27069L * adc) - 18169625L) >> 16; // Vref = 1.5V //c = ((45115L * adc) - 18169625L) >> 16; // Vref = 2.5V // k = ((27069L * adc) - 268467L) >> 16; // Vref = 1.5V //k = ((45115L * adc) - 268467L) >> 16; // Vref = 2.5V // f = ((48724L * adc) - 30634388L) >> 16; // Vref = 1.5V //f = ((81206L * adc) - 30634388L) >> 16; // Vref = 2.5V // // Convert to millivolts mv = (96094L * adc + 32768) >> 16; // Vref = 1.5V //mv = (160156L * adc + 32768) >> 16; // Vref = 2.5V // // Display on LCD print_int(f, 0); // Degrees F print_int(c, 2); // Degrees C print_int(k, 4); // Degrees K // #ifdef SHOW_ADC // print_v(adc, 72); // ADC print_v(mv, 78); // ADC millivolts #endif // // //__delay_cycles(100000); // } // } #pragma vector = ADC10_VECTOR // ADC conversion complete interrupt __interrupt void ADC10_ISR(void) // { // __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } //
     
    lcd.h

    typedef enum { lcd_command = 0, // Array of one or more commands lcd_data = 1, // Array of one or more bytes of data lcd_data_repeat = 2 // One byte of data repeated } lcd_cmd_type; void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type); void lcd_home(void); void lcd_pos(unsigned char x, unsigned char y); void lcd_clear(unsigned char x); void lcd_init(void); void lcd_print(char *s, unsigned x, unsigned y); void pd12(unsigned n, unsigned x, unsigned y);
     
    lcd.c

    #include #include "lcd.h" //static const unsigned TXD = BIT1; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; static const unsigned LCD_CLK = BIT5; static const unsigned LCD_BACKLIGHT = BIT6; static const unsigned LCD_DATA = BIT7; static const unsigned LCD_DC = BIT0; // PORT2 static const unsigned LCD_CE = BIT1; // PORT2 void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; P2OUT &= ~LCD_CE; do { mask = 0x0080; do { if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; mask >>= 1; } while(!(mask & 1)); if(!type) P2OUT &= ~LCD_DC; if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; P2OUT |= LCD_DC; if(!(type & 2)) ++cmd; } while(--len); P2OUT |= LCD_CE; } static const unsigned char home[] = { 0x40, 0x80 }; void lcd_home(void) { lcd_send(home, sizeof(home), lcd_command); } void lcd_pos(unsigned char x, unsigned char y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); } void lcd_clear(unsigned char x) { lcd_home(); lcd_send(&x, 504, lcd_data_repeat); lcd_home(); } void lcd_init(void) { static const unsigned char init[] = { 0x20 + 0x01, // function set - extended instructions enabled //0x80 + 64, // set vop (contrast) 0 - 127 0x80 + 66, // set vop (contrast) 0 - 127 0x04 + 0x02, // temperature control 0x10 + 0x03, // set bias system 0x20 + 0x00, // function set - chip active, horizontal addressing, basic instructions 0x08 + 0x04 // display control - normal mode }; P1REN = RXD | SWITCH; P1DIR = LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P1OUT = LCD_CLK | RXD | SWITCH | LCD_BACKLIGHT; P2REN = 0; P2DIR = LCD_DC | LCD_CE; P2OUT = LCD_CE; __delay_cycles(20000); P2OUT |= LCD_DC; __delay_cycles(20000); lcd_send(init, sizeof(init), lcd_command); } static const unsigned char font6x8[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 20 32 0x00, 0x00, 0x5F, 0x00, 0x00, // 21 33 ! 0x00, 0x07, 0x00, 0x07, 0x00, // 22 34 " 0x14, 0x7F, 0x14, 0x7F, 0x14, // 23 35 # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // 24 36 $ 0x23, 0x13, 0x08, 0x64, 0x62, // 25 37 % 0x36, 0x49, 0x56, 0x20, 0x50, // 26 38 & 0x00, 0x08, 0x07, 0x03, 0x00, // 27 39 ' 0x00, 0x1C, 0x22, 0x41, 0x00, // 28 40 ( 0x00, 0x41, 0x22, 0x1C, 0x00, // 29 41 ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // 2A 42 * 0x08, 0x08, 0x3E, 0x08, 0x08, // 2B 43 + 0x00, 0x40, 0x38, 0x18, 0x00, // 2C 44 , 0x08, 0x08, 0x08, 0x08, 0x08, // 2D 45 - 0x00, 0x00, 0x60, 0x60, 0x00, // 2E 46 . 0x20, 0x10, 0x08, 0x04, 0x02, // 2F 47 / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 30 48 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 31 49 1 0x42, 0x61, 0x51, 0x49, 0x46, // 32 50 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 33 51 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 34 52 4 0x27, 0x45, 0x45, 0x45, 0x39, // 35 53 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 36 54 6 0x41, 0x21, 0x11, 0x09, 0x07, // 37 55 7 0x36, 0x49, 0x49, 0x49, 0x36, // 38 56 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 39 57 9 0x00, 0x00, 0x14, 0x00, 0x00, // 3A 58 : 0x00, 0x00, 0x40, 0x34, 0x00, // 3B 59 ; 0x00, 0x08, 0x14, 0x22, 0x41, // 3C 60 < 0x14, 0x14, 0x14, 0x14, 0x14, // 3D 61 = 0x00, 0x41, 0x22, 0x14, 0x08, // 3E 62 > 0x02, 0x01, 0x51, 0x09, 0x06, // 3F 63 ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // 40 64 @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // 41 65 A 0x7F, 0x49, 0x49, 0x49, 0x36, // 42 66 B 0x3E, 0x41, 0x41, 0x41, 0x22, // 43 67 C 0x7F, 0x41, 0x41, 0x41, 0x3E, // 44 68 D 0x7F, 0x49, 0x49, 0x49, 0x41, // 45 69 E 0x7F, 0x09, 0x09, 0x09, 0x01, // 46 70 F 0x3E, 0x41, 0x49, 0x49, 0x7A, // 47 71 G 0x7F, 0x08, 0x08, 0x08, 0x7F, // 48 72 H 0x00, 0x41, 0x7F, 0x41, 0x00, // 49 73 I 0x20, 0x40, 0x41, 0x3F, 0x01, // 4A 74 J 0x7F, 0x08, 0x14, 0x22, 0x41, // 4B 75 K 0x7F, 0x40, 0x40, 0x40, 0x40, // 4C 76 L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // 4D 77 M 0x7F, 0x04, 0x08, 0x10, 0x7F, // 4E 78 N 0x3E, 0x41, 0x41, 0x41, 0x3E, // 4F 79 O 0x7F, 0x09, 0x09, 0x09, 0x06, // 50 80 P 0x3E, 0x41, 0x51, 0x21, 0x5E, // 51 81 Q 0x7F, 0x09, 0x19, 0x29, 0x46, // 52 82 R 0x26, 0x49, 0x49, 0x49, 0x32, // 53 83 S 0x01, 0x01, 0x7F, 0x01, 0x01, // 54 84 T 0x3F, 0x40, 0x40, 0x40, 0x3F, // 55 85 U 0x1F, 0x20, 0x40, 0x20, 0x1F, // 56 86 V 0x3F, 0x40, 0x38, 0x40, 0x3F, // 57 87 W 0x63, 0x14, 0x08, 0x14, 0x63, // 58 88 X 0x03, 0x04, 0x78, 0x04, 0x03, // 59 89 Y 0x61, 0x51, 0x49, 0x45, 0x43, // 5A 90 Z 0x00, 0x7F, 0x41, 0x41, 0x41, // 5B 91 [ 0x02, 0x04, 0x08, 0x10, 0x20, // 5C 92 '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // 5D 93 ] 0x04, 0x02, 0x01, 0x02, 0x04, // 5E 94 ^ 0x80, 0x80, 0x80, 0x80, 0x80, // 5F 95 _ 0x00, 0x03, 0x07, 0x08, 0x00, // 60 96 ' 0x20, 0x54, 0x54, 0x54, 0x78, // 61 97 a 0x7F, 0x28, 0x44, 0x44, 0x38, // 62 98 b 0x38, 0x44, 0x44, 0x44, 0x28, // 63 99 c 0x38, 0x44, 0x44, 0x28, 0x7F, // 64 100 d 0x38, 0x54, 0x54, 0x54, 0x18, // 65 101 e 0x00, 0x08, 0x7E, 0x09, 0x02, // 66 102 f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // 67 103 g 0x7F, 0x08, 0x04, 0x04, 0x78, // 68 104 h 0x00, 0x44, 0x7D, 0x40, 0x00, // 69 105 i 0x00, 0x20, 0x40, 0x40, 0x3D, // 6A 106 j 0x00, 0x7F, 0x10, 0x28, 0x44, // 6B 107 k 0x00, 0x41, 0x7F, 0x40, 0x00, // 6C 108 l 0x7C, 0x04, 0x78, 0x04, 0x78, // 6D 109 m 0x7C, 0x08, 0x04, 0x04, 0x78, // 6E 110 n 0x38, 0x44, 0x44, 0x44, 0x38, // 6F 111 o 0xFC, 0x18, 0x24, 0x24, 0x18, // 70 112 p 0x18, 0x24, 0x24, 0x18, 0xFC, // 71 113 q 0x7C, 0x08, 0x04, 0x04, 0x08, // 72 114 r 0x48, 0x54, 0x54, 0x54, 0x24, // 73 115 s 0x04, 0x04, 0x3F, 0x44, 0x24, // 74 116 t 0x3C, 0x40, 0x40, 0x20, 0x7C, // 75 117 u 0x1C, 0x20, 0x40, 0x20, 0x1C, // 76 118 v 0x3C, 0x40, 0x30, 0x40, 0x3C, // 77 119 w 0x44, 0x28, 0x10, 0x28, 0x44, // 78 120 x 0x4C, 0x90, 0x90, 0x90, 0x7C, // 79 121 y 0x44, 0x64, 0x54, 0x4C, 0x44, // 7A 122 z 0x00, 0x08, 0x36, 0x41, 0x00, // 7B 123 { 0x00, 0x00, 0x77, 0x00, 0x00, // 7C 124 | 0x00, 0x41, 0x36, 0x08, 0x00, // 7D 125 } 0x02, 0x01, 0x02, 0x04, 0x02, // 7E 126 ~ 0x00, 0x06, 0x09, 0x09, 0x06, // 7F 127 degrees }; void lcd_print(char *s, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); while(*s) { lcd_send(&font6x8[*s - 32][0], 5, lcd_data); lcd_send(&font6x8[0][0], 1, lcd_data); ++s; } } static const unsigned char num11x16[19][11 * 2] = { 0x00,0xF0,0xFC,0xFE,0x06,0x02,0x06,0xFE,0xFC,0xF0,0x00, // 0 0x00,0x07,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x07,0x00, 0x00,0x00,0x08,0x0C,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00, // 1 0x00,0x20,0x20,0x20,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x00, 0x00,0x0C,0x0E,0x06,0x02,0x02,0x86,0xFE,0x7C,0x38,0x00, // 2 0x00,0x30,0x38,0x3C,0x36,0x33,0x31,0x30,0x30,0x38,0x00, 0x00,0x0C,0x0E,0x86,0x82,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 3 0x00,0x18,0x38,0x30,0x20,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x00,0xC0,0x20,0x18,0x04,0xFE,0xFE,0xFE,0x00,0x00, // 4 0x00,0x03,0x02,0x02,0x02,0x22,0x3F,0x3F,0x3F,0x22,0x02, 0x00,0x00,0x7E,0x7E,0x46,0x46,0xC6,0xC6,0x86,0x00,0x00, // 5 0x00,0x18,0x38,0x30,0x20,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0xC0,0xF0,0xF8,0xFC,0x4C,0xC6,0xC2,0x82,0x00,0x00, // 6 0x00,0x0F,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0x06,0x06,0x06,0x06,0x06,0xC6,0xF6,0x3E,0x0E,0x00, // 7 0x00,0x00,0x00,0x30,0x3C,0x0F,0x03,0x00,0x00,0x00,0x00, 0x00,0x38,0x7C,0xFE,0xC6,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 8 0x00,0x0E,0x1F,0x3F,0x31,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x78,0xFC,0xFE,0x86,0x02,0x86,0xFE,0xFC,0xF8,0x00, // 9 0x00,0x00,0x00,0x21,0x21,0x31,0x1D,0x1F,0x0F,0x03,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : 0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . 0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x00,0x00,0x00,0x00, // / 0x00,0x30,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, // - 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x00,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xF0,0xF8,0x0C,0x06,0x02,0x02,0x02,0x02,0x0E,0x0C,0x00, // C 0x03,0x07,0x0C,0x18,0x10,0x10,0x10,0x10,0x1C,0x0C,0x00, 0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, // F 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0x40,0xE0,0xB0,0x18,0x0C,0x06,0x02,0x00,0x00, // K 0x1F,0x1F,0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x10,0x00 }; void pd12(unsigned n, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n], 11, lcd_data); c[1] = 0x41 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n] + 11, 11, lcd_data); }
×
×
  • Create New...