-
Content Count
38 -
Joined
-
Last visited
-
Days Won
1
Reputation Activity
-
websterling got a reaction from mbeals in Making SPI work
SPI.transfer only transfers 8 bits. This is what I'm using to transfer a 16 bit value to a DAC.
void SPIWrite(int value){ // value is 16 bits // take the LE ( SS ) pin high to inhibit data latching: digitalWrite(latchEnablePin, HIGH); MSB = highByte(value); LSB = lowByte(value); SPI.transfer(MSB); SPI.transfer(LSB); // take the LE ( SS ) pin low to latch the data: digitalWrite(latchEnablePin, LOW); }
-
websterling got a reaction from energia in TimerSerial and ADC Problem
I have a couple of things I'll share once I get them to a presentable point- maybe in the next week or two. This particular project is for a system to monitor carbon monoxide levels in the house during winter while heating with a wood stove.
Thanks for your efforts on Energia and on my bugs.
-
websterling reacted to energia in TimerSerial and ADC Problem
Found the bug. Below is the patch. The issue is that end() is not waiting for all bits to be transmitted.
Thanks for the report! Reporting issues helps us a lot with getting all the bugs out. Keep it up!
The 2553 also has a Hardware serial implementation available. The ASCIITable example under File->Examples->4.Communications is a good example to use.
Removing the end() and then begin() from the Sketch works around the issue. end() and then begin() are not needed.
--- a/hardware/msp430/libraries/TimerSerial/TimerSerial.cpp +++ b/hardware/msp430/libraries/TimerSerial/TimerSerial.cpp @@ -63,6 +63,9 @@ void TimerSerial::begin() void TimerSerial::end() { + while (TACCTL0 & CCIE) { + ; // wait for previous xmit to finish + } P1SEL = ~TX_PIN; // P1 functions select to default P1DIR = ~TX_PIN; // Input }
-
websterling reacted to Rickta59 in Weird Problem with analogRead() and mySerial.print()
After conferring with Robert he thinks and I concur that the problem is probably that the watchdog isr is kicking off
between the time the ADC capture starts and before it has completed. The watchdog timer reenables the CPU
which causes the analogRead code to continue execution when it really isn't ready. The code below seems to
work and is somewhat more power friendly. It uses a combination of sleeping and checking the ADC busy bit.
uint16_t analogRead(uint8_t pin) {
// make sure we have an ADC
#if defined(__MSP430_HAS_ADC10__)
// 0000 A0
// 0001 A1
// 0010 A2
// 0011 A3
// 0100 A4
// 0101 A5
// 0110 A6
// 0111 A7
// 1010 Internal temperature sensor
//TODO: Only int. temp. sensor requires Tsample > 30us.
// The below ADC configuration applies this rule to all channels right now.
// ADC10CLK = 5MHz / 5 = 1Mhz
// Tsample = S&H / ADC10CLK = 64 / 1 MHz = 64 us
// Tconver = 13 / ADC10CLK = 13 / 1 MHz = 13 us
// Total time per sample = Tconvert + Tsample = 64 + 13 = 67 us = ~15k samples / sec
if (pin > 7 && pin != 10) // ADC on pin?
return 0;
ADC10CTL0 &= ~ENC; // disable ADC
ADC10CTL0 = analog_reference | // set analog reference
ADC10ON | ADC10SHT_3 | ADC10IE; // turn ADC ON; sample + hold @ 64
-
websterling reacted to Rickta59 in Weird Problem with analogRead() and mySerial.print()
I took a look at this problem and I'm seeing the same results as you. I tried changing the analogRead code so that instead of sleeping and waiting for the ADC interrupt, it just sits in a busy while loop. That seems to fix it. Sitting in a busy loop isn't a very power friendly solution though.
If you want the gory details here is a patch:
diff --git a/hardware/msp430/cores/msp430/wiring_analog.c b/hardware/msp430/cores/msp430/wiring_analog.cindex 1bb2539..0543aa9 100644
--- a/hardware/msp430/cores/msp430/wiring_analog.c
+++ b/hardware/msp430/cores/msp430/wiring_analog.c
@@ -179,14 +179,22 @@ uint16_t analogRead(uint8_t pin)
if(pin > 7 && pin != 10) // ADC on pin?
return 0;
ADC10CTL0 &= ~ENC; // disable ADC
+#if 0
ADC10CTL0 = analog_reference + // set analog reference
- ADC10ON + ADC10SHT_3 + ADC10IE; // turn ADC ON; sample + hold @ 64
-
websterling reacted to energia in PWM Problem
Bug is fixed. Pull request with fix has been posted for review:
https://github.com/energia/Energia/pull/64/files
--- a/hardware/msp430/cores/msp430/wiring_digital.c +++ b/hardware/msp430/cores/msp430/wiring_digital.c @@ -79,9 +79,17 @@ void digitalWrite(uint8_t pin, uint8_t val) uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint16_t *out; + volatile uint16_t *sel; if (port == NOT_A_PORT) return; + /* + * Clear bit in PxSEL register to select GPIO function. Other functions like analogWrite(...) + * will set this bit so need to clear it. + */ + sel = portSelRegister(port); /* get the port function select register address */ + *sel &= ~bit; /* clear bit in pin function select register */ + out = portOutputRegister(port); if (val == LOW) {
-
websterling got a reaction from pine in Laser modules
AixiZ http://www.aixiz.com/store/index.php has a good selection of laser modules at reasonable prices.
I ordered 5 modules and some assorted parts for a recent project and they worked fine. They did ship one wrong part but corrected it promptly and didn't want the wrong part returned.
-
websterling got a reaction from MarkoeZ in KickSat -- Your personal spacecraft in space!
Came across this and thought others might find it interesting:
http://www.kickstarter.com/projects/251588730/kicksat-your-personal-spacecraft-in-space
Check out this question in the FAQ at the bottom of the page-
"If I donate enough to receive a developers kit can I really fly my own code?"
A paper on the concept:
http://spectrum.ieee.org/aerospace/satellites/exploring-space-with-chipsized-satellites
The Cornell site where the concept originated:
http://www.spacecraftresearch.com/MII/MII_overview.html
-
websterling got a reaction from Robby in Using 3 wires to control parallel LCD display
If anyone is interested, I found this display that uses 3 volts for both the display and backlight
http://www.newhavendisplay.com/index.ph ... cts_id=282
onlinecomponents.com has them for $7.00 + shipping
-
websterling got a reaction from nuetron in Converting a 3-Digit Number to Characters for a LCD Display
I'm working on a project requiring a calculated 3-digit number to be updated periodically on a LCD display and came up with a simple solution to convert the number to characters. I'm posting it here on the chance that others might find it useful.
I first thought of sprintf, but it's way too big for a msp430g2452. I found and tried tfp_sprintf, but it was also too big. I tried sstream (apparently the preferred method) but it caused 100+ errors in CCS, somewhere in the TI include files.
I found this to convert a single digit to a character
character = (char)(((int)'0') + digit_to_convert);
I had a 3 digit number to convert; after a bit of thought I came up with this-
// All number variables are type int // joules is the calculated 3-digit number- it is displayed with leading joules = total_seconds/3.2; joules100 = joules/100; // joules100 is the 100's place digit joules10 = (joules/10)%10; // joules10 is the 10's place digit joules1 = joules%10; // joules1 is the 1's place digit // The complete message is in a 32 element array- these 3 digits are elements 22-24 message[22] = (char)(((int)'0')+joules100); message[23] = (char)(((int)'0')+joules10); message[24] = (char)(((int)'0')+joules1);
-
websterling got a reaction from bluehash in Converting a 3-Digit Number to Characters for a LCD Display
I'm working on a project requiring a calculated 3-digit number to be updated periodically on a LCD display and came up with a simple solution to convert the number to characters. I'm posting it here on the chance that others might find it useful.
I first thought of sprintf, but it's way too big for a msp430g2452. I found and tried tfp_sprintf, but it was also too big. I tried sstream (apparently the preferred method) but it caused 100+ errors in CCS, somewhere in the TI include files.
I found this to convert a single digit to a character
character = (char)(((int)'0') + digit_to_convert);
I had a 3 digit number to convert; after a bit of thought I came up with this-
// All number variables are type int // joules is the calculated 3-digit number- it is displayed with leading joules = total_seconds/3.2; joules100 = joules/100; // joules100 is the 100's place digit joules10 = (joules/10)%10; // joules10 is the 10's place digit joules1 = joules%10; // joules1 is the 1's place digit // The complete message is in a 32 element array- these 3 digits are elements 22-24 message[22] = (char)(((int)'0')+joules100); message[23] = (char)(((int)'0')+joules10); message[24] = (char)(((int)'0')+joules1);
-
websterling got a reaction from Fe2o3Fish in Using 3 wires to control parallel LCD display
If anyone is interested, I found this display that uses 3 volts for both the display and backlight
http://www.newhavendisplay.com/index.ph ... cts_id=282
onlinecomponents.com has them for $7.00 + shipping
-
websterling got a reaction from Mac in Using 3 wires to control parallel LCD display
If anyone is interested, I found this display that uses 3 volts for both the display and backlight
http://www.newhavendisplay.com/index.ph ... cts_id=282
onlinecomponents.com has them for $7.00 + shipping
-
websterling got a reaction from RobG in Using 3 wires to control parallel LCD display
If anyone is interested, I found this display that uses 3 volts for both the display and backlight
http://www.newhavendisplay.com/index.ph ... cts_id=282
onlinecomponents.com has them for $7.00 + shipping
-
websterling got a reaction from bluehash in RGB LED Lamp
Actually, I had made all of the changes necessary to port this to CCS. The problem was that, in the original code, TACCRO was set too low. Changing TACCRO=70 to TACCRO=100 in int main(void) was the fix.
If anyone else is interested, the code follows. It only took 3 nights to figure this out...
#include #include #include #include /****************************************************/ #define LED_BIT (BIT0|BIT1|BIT2) // Timer0 ticks #define TICKS_PER_SEC (1000000 / TACCR0) // 1MHz clock /****************************************************/ static uint8_t led_brightness[3] = {0x00,0x00,0x00}; static uint32_t sys_ticks = 0; static bool ADCDone = false; static uint16_t ADCValue; /****************************************************/ static void cpu_init(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT // configure system clock BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // SMCLK = DCO = 1MHz // _enable_interrupt(); } // Binary Code Modulation static void bcm_tick(uint8_t led_ticks) { uint8_t bcm = 0x00; switch(led_ticks) { case 0x1: case 0x2: case 0x4: case 0x8: case 0x10: case 0x20: case 0x40: case 0x80: // led_ticks is a power of 2 if (led_brightness[0] & led_ticks) bcm |= BIT0; if (led_brightness[1] & led_ticks) bcm |= BIT1; if (led_brightness[2] & led_ticks) bcm |= BIT2; P1OUT = bcm; } } // Timer0 ISR //interrupt(TIMERA0_VECTOR) TIMERA0_ISR(void) #pragma vector=TIMERA0_VECTOR __interrupt void TIMERA0_ISR (void) { bcm_tick(sys_ticks); sys_ticks++; } void Single_Measure(unsigned int chan) { ADC10CTL0 &= ~ENC; // Disable ADC ADC10CTL0 = ADC10SHT_3 + ADC10ON + ADC10IE; // 16 clock ticks, ADC On, enable ADC interrupt ADC10CTL1 = ADC10SSEL_3 + chan; // Set 'chan', SMCLK ADC10CTL0 |= ENC + ADC10SC; // Enable and start conversion } //interrupt(ADC10_VECTOR) ADC10_ISR(void) #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR (void) { ADCValue = ADC10MEM; ADCDone = true; } void hue2rgb(volatile uint8_t *r, volatile uint8_t *g, volatile uint8_t *b, uint16_t h) { uint16_t f; f = ( (h%60) <<8 ) / 60; h /= 60; switch(h) { case 0: *r = 0xFF; *g = f; *b = 0; break; case 1: *r = 0xFF - f; *g = 0xFF; *b = 0; break; case 2: *r = 0; *g = 0xFF; *b = f; break; case 3: *r = 0; *g = 0xFF - f; *b = 0xFF; break; case 4: *r = f; *g = 0; *b = 0xFF; break; default: *r = 0xFF; *g = 0; *b = 0xFF - f; break; } } int main(void) { cpu_init(); // setup LED pins P1DIR |= LED_BIT; // All LED pins as outputs P1OUT &= ~LED_BIT; // Turn off LED // TimerA SMCLK in UP mode TACTL = TASSEL_2 | MC_1; // Enable interrupt for TACCR0 match TACCTL0 = CCIE; // Set TACCR0, starts timer //TACCR0 = 70; // This must be short enough to look good and long enough for TIMER0_ISR to complete TACCR0 = 100; // This must be short enough to look good and long enough for TIMER0_ISR to complete //eint(); __enable_interrupt(); Single_Measure(INCH_7); while(1) { if (ADCDone) { ADCDone = false; hue2rgb(led_brightness+0, led_brightness+1, led_brightness+2, ((uint32_t)ADCValue*360)/1024); Single_Measure(INCH_7); } } }
-
websterling got a reaction from jsolarski in RGB LED Lamp
Actually, I had made all of the changes necessary to port this to CCS. The problem was that, in the original code, TACCRO was set too low. Changing TACCRO=70 to TACCRO=100 in int main(void) was the fix.
If anyone else is interested, the code follows. It only took 3 nights to figure this out...
#include #include #include #include /****************************************************/ #define LED_BIT (BIT0|BIT1|BIT2) // Timer0 ticks #define TICKS_PER_SEC (1000000 / TACCR0) // 1MHz clock /****************************************************/ static uint8_t led_brightness[3] = {0x00,0x00,0x00}; static uint32_t sys_ticks = 0; static bool ADCDone = false; static uint16_t ADCValue; /****************************************************/ static void cpu_init(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT // configure system clock BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // SMCLK = DCO = 1MHz // _enable_interrupt(); } // Binary Code Modulation static void bcm_tick(uint8_t led_ticks) { uint8_t bcm = 0x00; switch(led_ticks) { case 0x1: case 0x2: case 0x4: case 0x8: case 0x10: case 0x20: case 0x40: case 0x80: // led_ticks is a power of 2 if (led_brightness[0] & led_ticks) bcm |= BIT0; if (led_brightness[1] & led_ticks) bcm |= BIT1; if (led_brightness[2] & led_ticks) bcm |= BIT2; P1OUT = bcm; } } // Timer0 ISR //interrupt(TIMERA0_VECTOR) TIMERA0_ISR(void) #pragma vector=TIMERA0_VECTOR __interrupt void TIMERA0_ISR (void) { bcm_tick(sys_ticks); sys_ticks++; } void Single_Measure(unsigned int chan) { ADC10CTL0 &= ~ENC; // Disable ADC ADC10CTL0 = ADC10SHT_3 + ADC10ON + ADC10IE; // 16 clock ticks, ADC On, enable ADC interrupt ADC10CTL1 = ADC10SSEL_3 + chan; // Set 'chan', SMCLK ADC10CTL0 |= ENC + ADC10SC; // Enable and start conversion } //interrupt(ADC10_VECTOR) ADC10_ISR(void) #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR (void) { ADCValue = ADC10MEM; ADCDone = true; } void hue2rgb(volatile uint8_t *r, volatile uint8_t *g, volatile uint8_t *b, uint16_t h) { uint16_t f; f = ( (h%60) <<8 ) / 60; h /= 60; switch(h) { case 0: *r = 0xFF; *g = f; *b = 0; break; case 1: *r = 0xFF - f; *g = 0xFF; *b = 0; break; case 2: *r = 0; *g = 0xFF; *b = f; break; case 3: *r = 0; *g = 0xFF - f; *b = 0xFF; break; case 4: *r = f; *g = 0; *b = 0xFF; break; default: *r = 0xFF; *g = 0; *b = 0xFF - f; break; } } int main(void) { cpu_init(); // setup LED pins P1DIR |= LED_BIT; // All LED pins as outputs P1OUT &= ~LED_BIT; // Turn off LED // TimerA SMCLK in UP mode TACTL = TASSEL_2 | MC_1; // Enable interrupt for TACCR0 match TACCTL0 = CCIE; // Set TACCR0, starts timer //TACCR0 = 70; // This must be short enough to look good and long enough for TIMER0_ISR to complete TACCR0 = 100; // This must be short enough to look good and long enough for TIMER0_ISR to complete //eint(); __enable_interrupt(); Single_Measure(INCH_7); while(1) { if (ADCDone) { ADCDone = false; hue2rgb(led_brightness+0, led_brightness+1, led_brightness+2, ((uint32_t)ADCValue*360)/1024); Single_Measure(INCH_7); } } }