-
Content Count
77 -
Joined
-
Last visited
-
Days Won
2
Reputation Activity
-
David Bender got a reaction from timotet in Interface push button rotary encoder on 1 analog input
I had a lack of digital input pins for a pushbutton rotary encoder switch so I used an analog input.
I wrote up my results here: https://analog10.com/posts/rotary_encoder_analog_input.html
It works pretty well except for an occasional reverse tick but that's probably a flaw in my code.
-
David Bender got a reaction from Automate in Reading and Powering a Digital Dial Gauge
Harbor Freight offers a decent deal on a digital gauge that also communicates its reading (much like a Chinese calipers).
I built up an MSP430 based solution to retransmit this data via UART and externally power the dial gauge (eliminating the need for a button cell battery).
Project details are at https://analog10.com/posts/external_power_for_the_pittsburgh_dial_gauge.html
Code is at https://github.com/analog10/Digital_Dial_Gauge_Reader
Happy Holidays
-
David Bender got a reaction from pine in Reading and Powering a Digital Dial Gauge
Harbor Freight offers a decent deal on a digital gauge that also communicates its reading (much like a Chinese calipers).
I built up an MSP430 based solution to retransmit this data via UART and externally power the dial gauge (eliminating the need for a button cell battery).
Project details are at https://analog10.com/posts/external_power_for_the_pittsburgh_dial_gauge.html
Code is at https://github.com/analog10/Digital_Dial_Gauge_Reader
Happy Holidays
-
David Bender got a reaction from spirilis in TM4C129 Ethernet client: http request loss when receiving continuous inquiries
You probably can get decent web performance with the TM4C129. You can't use a naive web server though. I've written an embedded web server for my client (on an ARM chip as well) and can recommend the following:
1) Don't buffer the client request; try to parse the request as the data comes in. 98% of your requests are GETs and do not require buffering. Consequently you can boost the number of sockets you can process at a time.
2) I recommended trying Connection: close because I thought the browser may have been trying to reuse the socket and your code didn't seem to support that. Connection: close is BAD precisely because the client will use more socket resources. So try to reuse the socket.
3) Send etags back on all GETs and parse etags from the client. 304 responses take way less bandwidth.
4) I'm not sure what client.write() does, but it does not seem to distinguish between RAM and flash. LWIP can operate way more efficiently if it does not have to make a second copy of the data.
5) Though you can \n as a line terminator, just send \r\n. Do it.
6) Be nice to the user and send back a 429 when you've received too many web requests. So much nicer than a hang up.
-
David Bender reacted to jpnorair in A more efficient circular FIFO buffer
Ring buffers are not good solutions for fast performance. For that, you want to use an A/B buffer. Yes, you need double the memory, but that's the tradeoff. To get "best of both worlds" I've found that, quite often, it is faster to do a DMA memcpy to shift the buffer (only happens when limit is reached) than it is to do the ring-buffer logic on every byte entered or removed. On MSP430's with DMA you can move 2 bytes in 1 cycle, plus some setup, whereas all those if's probably burn 20-30 cycles for each byte entered/removed. So do the arithmetic and figure out what is the best choice based on your buffer size.
-
David Bender got a reaction from Rickta59 in TM4C129 Ethernet client: http request loss when receiving continuous inquiries
Why don't you try setting the Connection:close header on the tiger request?
-
David Bender got a reaction from Rickta59 in A more efficient circular FIFO buffer
This isn't actually the original code I used; this is the "cleaned up" version to illustrate the concepts. It seems I copied the wrong file up; I made the edits that should fix it.
-
David Bender got a reaction from abecedarian in How fast does this execute?
This sure is a rapid prototype, but the signal he's trying to measure goes down to about 200us in period.
So using pulseIn is going to have wildly inaccurate results at his top end.
Looking at the source code for pulseIn almost made me vomit.
Ignores this thing called TimerA, susceptible to interrupts, etc.
pulseIn may be OK for measuring human reaction time, but certainly nothing faster.
-
David Bender got a reaction from abecedarian in How fast does this execute?
OK so far so good. (The following may be obvious but I think I'm learning something here...)
As you keep specifying your simulation requirements in frequency, I am assuming you want a UNIFORM frequency resolution.
I may be wrong, but you in general cannot linearly specify frequency, only period (there is 1 exception)*.
Frequency changes asymptotically WRT to period, so you end up with a linear region only a fraction of your whole range.
Higher frequencies will have much less resolution than lower frequencies.
So for the crank, 107Hz is approximately 10000us and 6000Hz is approximately 166us.
A PWM peripheral running at 1 MHz would have a TACCR0 at 10000 at the slowest, and 166 at the fastest (36Hz worst res).
A PWM peripheral running at 4 MHz would have a TACCR0 at 40000 at the slowest, and 666 at the fastest (2Hz worst res).
(note these are off by 1, since TA0R starts at 0)
The exception is you can linearly control the DCO, which is basically a linear (5) bit mixer between two frequencies, giving you an extra 1/32 resolution.
VCC will also affect your effective frequency, so make sure it does not change.
If you use a synchronous protocol like SPI or I2C, you could turn one of your G2553s into a slave square wave generator with fairly precise control (UART would not work since it is clock dependent).
-
David Bender reacted to abecedarian in How fast does this execute?
900ms sounds a bit shy of the target I'm hoping for.
Re-reading things here, allow me to apologize for the confusion, and maybe rephrase / restate the intentions. I got a little ahead of myself.
Goal(s)- simulate various sensors as would be installed on the engine including manifold pressure and temperature, coolant temperature, throttle position and the (a) crankshaft and ( camshaft trigger signals. Analog sensors like temp and pressure can probably be done with linear pots; I'm fine with that. The crankshaft signals will come at a rate of 32 pulses per crankshaft revolution, with approximately 50% duty, as far as I can tell. Crank trigger setup-
*note I am only going to use one of the two VR sensors- this is a modified stock CX/GL pickup setup, but I'm trying to avoid modifying anything mechanical on this or similar bikes if possible.
The camshaft is similar, but with only a single tooth and two pickups, again of which I'm only using one.
The 11.25 number came about because 360 degrees divided across 32 teeth is 11.25 degrees from tooth to tooth. That was my mistake for including that since the ECU will be responsible for decoding and calculating when things should fire. I'll delve into what I think should happen there, if anyone is interested.
So back on topic: it seems that to simulate 200 RPM, I'd need to generate (200/60*32) pulses per second, or ~107 Hz, for the crank, and ~3 Hz for the cam; sounds more realistic. At 11000 RPM, that's ~5867 & 184 PPS for crank and cam, respectively. Using PWM for the signal seems logical in retrospect since they are continuous, repetitive signals, but isn't around 250Hz the lower end of what's possible? Actually, 200 RPM is probably low even, and I could probably get away with 500- but I'm trying to account for worse-case possible engine start speeds... and 200 RPM is probably a dead battery anyways so....
Crankshaft trigger duty cycle will not change and it's likely 50% will work fine- ~1mm wide tooth face & ~1mm wide valley between teeth. I'll have to figure out what the cam should be since it has a similar tooth profile to the crank sensor, but has only one tooth and rotates 1/2 crank speed... maybe turn on with one crank tooth then turn off with the next. I also still have to determine the cam sensor's absolute placement / relation with regards to the teeth on the crank sensor, as in does it exactly coincide with a tip or valley on the crank sensor, or somewhere in between (mostly relevant to the ECU's operation, not this).
To add, I've no issue dedicating a Stellaris or Tiva Launchpad for this if either is more appropriate.
I'm babbling, yet again.
-
David Bender got a reaction from abecedarian in How fast does this execute?
If you want to see how fast the loop is going then refer to the UART DCO Calibrator timer interrupt; it is recording the time between pulses. If you run at 16MHz, those pulses will be DCO clock counts. If you output those pulses to the UART (at 115200 you should be able to keep up) then you'll know the period between pulses.
As for the other stuff I apologize I still lost about whether you are generating crank/cam pulses or cylinder firing (code seems to be cylinder but your explanation was about crank/cam?) I don't understand why you chose your units to be degrees when you are counting gear tooth pulses, why not base everying on gear teeth?
-
David Bender got a reaction from abecedarian in How fast does this execute?
Oh OK, I didn't realize this was a simulator (duh, you said so). I see what you are doing now; the important thing is to have these impulses at the proper phase from each other.
Since you have a bunch of G2553 chips, devote one to just the simulated crankshaft.
The reason being is you should simulate the "speed" of your crankshaft by changing the speed of the DCO.
You can scale the DCO speed/up down, refer to https://github.com/analog10/UART_DCO_Calibrator
As long as your signals are in the proper phase for 1 frequency, this should work for all frequencies
-
David Bender got a reaction from oPossum in "spikes" in the ultrasonic reading
Why are you comparing TA1CCR0 to a constant? You set it only once in the code and never change it again...
if((TA1CTL & TAIFG) && (TA1CCR0 < 0x1000)) fall += TA1CCR0; -
David Bender got a reaction from greeeg in A higher performing timer UART snippet
greeeg, this version should work for you.
The stop bits look good on this one.
I added a waiting transmit buffer so gapless transmission is now possible.
I think the transmit path for data bits is a few clocks faster too now.
(though xmit_char() is a little slower)
#include <stdint.h> #include <msp430g2231.h> #define BAUD 9600 enum { /* P1 */ P1_STATUS_LED_BIT = BIT0 ,P1_TX = BIT2 ,P1_RX = BIT1 }; volatile uint16_t tx_wait = 0; volatile uint16_t tx_char = 0; volatile uint16_t rx_ready = 0; /* TODO Could use constants here for efficiency.. * but it would be nice to design for runtime set baud rates. */ uint16_t rx_ticks_per_bit = F_CPU / BAUD; uint16_t rx_ticks_per_bit_3_2 = 3 * F_CPU / BAUD / 2; inline void ser_init(void){ TA0CTL = TASSEL_2 | MC_2 | TACLR; TA0CCTL0 = SCS | CM_2 | CAP | CCIE; /* Note OUT is an indication of "idle". * Thankfully OUT is 4, which is covered by the constant generator. * Set CCIFG to indicate stop bit completed. */ TA0CCTL1 = OUT | CCIFG; P1SEL |= P1_RX | P1_TX; } /* For some reason static prevents inlining... */ void xmit_char(uint16_t c){ /* If busy transmitting then populate the wait buffer. */ __dint(); if(!(TA0CCTL1 & OUT)){ register int16_t value = c; c |= 0x100; c <<= 1; tx_wait = c; __eint(); /* Wait for wait buffer to clear. */ while(tx_wait); return; } __eint(); /* Wait for stop bit to finish transmitting. */ while(!(TA0CCTL1 & CCIFG)); /* Let's get started on the stop bit now.. */ TA0CCTL1 = OUTMOD_0; /* Schedule timer transition. */ TA0CCR1 = TAR; TA0CCR1 += rx_ticks_per_bit; /* Add stop bit */ register int16_t value = c; value |= 0x100; /* Shift the LSB into the C bit of the SR. */ value >>= 1; tx_char = value; /* This ASM clause defines output bit at CCR1 trigger. */ __asm__ ( " mov #176,%[value]\n" " jnc 10f\n" " xor #128,%[value]\n" "10:" " mov %[value],%[cctl]\n" : : [cctl] "m" (TA0CCTL1), /* 3 */ [value] "r" (value) /* 3 */ ); } __attribute__((interrupt(TIMER0_A1_VECTOR))) void SoftUART_TX(void){ __asm__ ( /* Clear TAIV; only TA0.1 is enabled so no read necessary. */ " tst &0x012e\n" /* Schedule next bit transition. */ " add %[TICKS],%[ccr]\n" /* Assume the next bit is a 1. * Note if the carry bit is 1 then assumption was correct. * Move the next bit to output to the C flag; * If the result is nonzero */ " mov %[init],%[cctl]\n" " rra %[tx_buf]\n" " jnz 3f\n" /* If the carry bit is nonzero, check the buffer for pending data. */ " jnc 5f\n" /* At this point, scheduled the final stop bit. * Wait buffer may have more stuff. * XOR because nonzero result sets Z flag. * If not then set to idle. */ " xor %[tx_w], %[tx_buf]\n" " mov #0,%[tx_w]\n" " jnz 4f\n" /* Value is zero, move into the end state. */ " mov %[end],%[cctl]\n" " jmp 4f\n" /* Set to idle. (setting to OUT) */ "5:\n" " mov #4,%[cctl]\n" " jmp 4f\n" /* Otherwise assume we will output 0. * If the stop bit is still in tx_buf go to the end. */ "3:\n" " jc 4f\n" " bis %2,%[cctl]\n" "4:\n" : : [TICKS] "m" (rx_ticks_per_bit), /* 0 */ [ccr] "m" (TA0CCR1), /* 1 */ [mod2] "i" (OUTMOD2), /* 2 */ [cctl] "m" (TA0CCTL1), /* 3 */ [tx_buf] "m" (tx_char), /* 4 */ [tx_w] "m" (tx_wait), /* 5 */ [init] "i" (OUTMOD_1 | CCIE), /* 6 */ [end] "i" (OUTMOD_1 | OUT) /* 6 */ : "cc" ); } __attribute__((interrupt(TIMER0_A0_VECTOR))) void SoftUART_RX(void){ static uint16_t rx_buffer; register int16_t tmp = TA0CCTL0; if(tmp & CAP){ TA0CCR0 += rx_ticks_per_bit_3_2; tmp = 0x0100; TA0CCTL0 &= ~CAP; } else{ TA0CCR0 += rx_ticks_per_bit; tmp &= SCCI; tmp |= rx_buffer; tmp >>= 1; if(tmp & 0x1){ TA0CCTL0 |= CAP; __bic_SR_register_on_exit(CPUOFF); rx_ready = tmp; return; } } rx_buffer = tmp; } int main(void){ WDTCTL = WDTPW | WDTHOLD; /* Set to 1 MHz. */ BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; /* SMCLK = DCO / DIVS = nMHz */ /* ACLK = VLO = ~ 12 KHz */ BCSCTL2 &= ~(DIVS_0); BCSCTL3 |= LFXT1S_2; /* Disable external crystal. */ P2SEL = 0; /* Enable RX pullup */ P1REN = BIT1; P1OUT = P1_TX | P1_RX; P1DIR = P1_STATUS_LED_BIT | P1_TX; /* Set up serial. */ ser_init(); __eint(); /* Test sending multiple in a row */ xmit_char('R'); xmit_char('E'); xmit_char('S'); xmit_char('E'); xmit_char('T'); xmit_char('\n'); while(1){ LPM0; /* Handle rx. */ int16_t tmp = rx_ready; if(tmp){ /* Shift to align with byte. */ tmp >>= 2; tmp &= 0xFF; /* Send back received character. */ xmit_char(tmp); rx_ready = 0; /* Toggle LED on each transmit. */ P1OUT ^= P1_STATUS_LED_BIT; } } } -
David Bender got a reaction from tripwire in Yet another DCO calibrator
This DCO calibrator starts with me not having a crystal on my board, and stealing rick's idea about using the UART to calibrate the DCO. It works without the UART peripheral or capture compare. The host sends the 'U' character and the micro responds with what adjustment it made, or that it calibrated to the target frequency. When the micro is calibrated, it sends the calibration constant values to the host, which prints them for the user. I used an oscope to verify the frequency on the P1.4's SMCLK output.
Code is here:
https://github.com/analog10/UART_DCO_Calibrator
rick's original concept is here:
https://github.com/RickKimball/msp430_code/blob/master/fabooh/examples/serial/dco_calibrate/goldilocks.cpp
-
David Bender got a reaction from chicken in Building low power into Energia
Add the ability to set an arbitrary DCO speed at compile time. Add a DCO calibration option to Energia.
-
David Bender got a reaction from bluehash in Yet another DCO calibrator
This DCO calibrator starts with me not having a crystal on my board, and stealing rick's idea about using the UART to calibrate the DCO. It works without the UART peripheral or capture compare. The host sends the 'U' character and the micro responds with what adjustment it made, or that it calibrated to the target frequency. When the micro is calibrated, it sends the calibration constant values to the host, which prints them for the user. I used an oscope to verify the frequency on the P1.4's SMCLK output.
Code is here:
https://github.com/analog10/UART_DCO_Calibrator
rick's original concept is here:
https://github.com/RickKimball/msp430_code/blob/master/fabooh/examples/serial/dco_calibrate/goldilocks.cpp
-
David Bender got a reaction from tingo in Yet another DCO calibrator
This DCO calibrator starts with me not having a crystal on my board, and stealing rick's idea about using the UART to calibrate the DCO. It works without the UART peripheral or capture compare. The host sends the 'U' character and the micro responds with what adjustment it made, or that it calibrated to the target frequency. When the micro is calibrated, it sends the calibration constant values to the host, which prints them for the user. I used an oscope to verify the frequency on the P1.4's SMCLK output.
Code is here:
https://github.com/analog10/UART_DCO_Calibrator
rick's original concept is here:
https://github.com/RickKimball/msp430_code/blob/master/fabooh/examples/serial/dco_calibrate/goldilocks.cpp
-
David Bender got a reaction from GeekDoc in Yet another DCO calibrator
This DCO calibrator starts with me not having a crystal on my board, and stealing rick's idea about using the UART to calibrate the DCO. It works without the UART peripheral or capture compare. The host sends the 'U' character and the micro responds with what adjustment it made, or that it calibrated to the target frequency. When the micro is calibrated, it sends the calibration constant values to the host, which prints them for the user. I used an oscope to verify the frequency on the P1.4's SMCLK output.
Code is here:
https://github.com/analog10/UART_DCO_Calibrator
rick's original concept is here:
https://github.com/RickKimball/msp430_code/blob/master/fabooh/examples/serial/dco_calibrate/goldilocks.cpp
-
David Bender got a reaction from Rickta59 in Yet another DCO calibrator
This DCO calibrator starts with me not having a crystal on my board, and stealing rick's idea about using the UART to calibrate the DCO. It works without the UART peripheral or capture compare. The host sends the 'U' character and the micro responds with what adjustment it made, or that it calibrated to the target frequency. When the micro is calibrated, it sends the calibration constant values to the host, which prints them for the user. I used an oscope to verify the frequency on the P1.4's SMCLK output.
Code is here:
https://github.com/analog10/UART_DCO_Calibrator
rick's original concept is here:
https://github.com/RickKimball/msp430_code/blob/master/fabooh/examples/serial/dco_calibrate/goldilocks.cpp
-
David Bender got a reaction from bluehash in SwitchPad: LaunchPad Gender Changer
Hi All,
I got fed up with male headers on the LaunchPad, so I made up a small PCB to gender change the LaunchPad. It has the nice side effect that it is easy to switch my LaunchPad among different projects. Check it out
https://analog10.com/posts/000_switchpad.html
Thanks,
Dave
-
David Bender got a reaction from johnnyb in SwitchPad: LaunchPad Gender Changer
Hi All,
I got fed up with male headers on the LaunchPad, so I made up a small PCB to gender change the LaunchPad. It has the nice side effect that it is easy to switch my LaunchPad among different projects. Check it out
https://analog10.com/posts/000_switchpad.html
Thanks,
Dave
-
David Bender got a reaction from roadrunner84 in SwitchPad: LaunchPad Gender Changer
Hi All,
I got fed up with male headers on the LaunchPad, so I made up a small PCB to gender change the LaunchPad. It has the nice side effect that it is easy to switch my LaunchPad among different projects. Check it out
https://analog10.com/posts/000_switchpad.html
Thanks,
Dave
-
David Bender got a reaction from dubnet in LaunchPad compatible 28pin G2553 breakout board
Hi,
I am working on a breakout board that plugs into a Launchpad and exposes the extra P3 port. My current rev doesn't follow the LaunchPad 40 pin "standard" but I guess it can be adjusted in the next rev. If anybody is interested in using it please respond to this thread.
Image:
http://uploads.oshpark.com/uploads/project/top_image/6PmSJYiP/i.png
It has nonpopulated passives for standalone operation as well.
-
David Bender got a reaction from Rickta59 in LaunchPad compatible 28pin G2553 breakout board
After some tribulations with ESD and finding some copper pour fill issues I finally have a working board. It is running the blink demo. (edit: original pic showed unprogrammed 2252 in the DIP socket; new pic shows chip removed, which is what I intended)