Цифровая шкала с LED линейкой на MSP430

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Ser60 писал(а):У меня есть таком МК на работе. Я завтра принесу домой, тогда продолжим.

Пойду я тоже спать.
Реклама
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Ser60 »

Проверил МК, ближайший нашел только MSP430G2452. Вот работающий код. Будет работать и на Вашем МК, поменяйте его название в первой строке. АЦП начинает преобразование по таймеру TimerA, канал 0. По завершении преобразования происходит прерывание и в нем поджигаются нужные светики. Я поменял 2 последних порога, по-моему в них были опечатки.

Советую зашунтировать вход АЦП (вывод 2) керамикой 0.1 мкф на землю.

Спойлер

Код: Выделить всё

#include <msp430g2452.h>

//1 BIT2 1DIR
//2 BIT3 1DIR
//3 BIT4 1DIR
//4 BIT5 1DIR
//5 BIT0 2DIR
//6 BIT1 2DIR
//7 BIT2 2DIR
//8 BIT3 2DIR
//9 BIT4 2DIR
//10 BIT5 2DIR
//11 BIT6 1DIR
//12 BIT7 1DIR
//13 BIT7 2DIR
//14 BIT6 2DIR

void ADC_init(void);                          // function prototypes           
void Ports_init(void);
void TimerA_init(void);

void main( void )
{
   WDTCTL = WDTPW + WDTHOLD;               // disable watchdog                         
    
   Ports_init();                        // init P1 and P2
   ADC_init();                           // init ADC
   TimerA_init();                        // init TimerA

   for (;;)
     __low_power_mode_0();                  // enter sleep mode

}//main

void TimerA_init(void)
{
   TACCR0 = 3125;                     // ADC trigger period ~22 мсек
   TACCTL0 = OUTMOD_4;                     // toggle OUT0 to trigger ADC
   TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR;      // SMCLK/8, up mode, start
}

void Ports_init(void)
{
   P1DIR = 0xFF;                        // configure port for output
   P1OUT = 0;                                    // init port
   P2DIR = 0xFF;                        // configure port for output
   P2SEL = 0;                           // I/O on XTAL pins
   P2OUT = 0;                                  // init port   


void ADC_init(void)
{
   ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE;   // 16 clocks sample-and-hold
   ADC10CTL1 = SHS_2 + CONSEQ_2;            // trigger by TA0
   ADC10AE0  = BIT0;                       // set ADC channel 0                         
   ADC10CTL0 |= ENC;                     // enable conversion
}

#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void)            // ADC10 ISR
{
    float volts = ADC10MEM * 0.0032258;          // convert ADC into volts
   char led1 = 0;                        // PORT1 leds stati
   char led2 = 0;                        // PORT2 leds stati
      
    if (volts >= 1.2)  led1 |= BIT2;         // new led states
    if (volts >= 1.36) led1 |= BIT3;
    if (volts >= 1.52) led1 |= BIT4;
    if (volts >= 1.69) led1 |= BIT5;
    if (volts >= 1.85) led2 |= BIT0;
    if (volts >= 2.01) led2 |= BIT1;
    if (volts >= 2.17) led2 |= BIT2;
    if (volts >= 2.33) led2 |= BIT3;
    if (volts >= 2.5)  led2 |= BIT4;
    if (volts >= 2.67) led2 |= BIT5;
    if (volts >= 2.82) led1 |= BIT6;
    if (volts >= 2.99) led1 |= BIT7;
    if (volts >= 3.15) led2 |= BIT7;
    if (volts >= 3.25) led2 |= BIT6;
   P1OUT = led1;                        // copy led states to ports
   P2OUT = led2;

Реклама
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Спойлер

Код: Выделить всё

#include <msp430g2452.h>

//1 BIT2 1DIR
//2 BIT3 1DIR
//3 BIT4 1DIR
//4 BIT5 1DIR
//5 BIT0 2DIR
//6 BIT1 2DIR
//7 BIT2 2DIR
//8 BIT3 2DIR
//9 BIT4 2DIR
//10 BIT5 2DIR
//11 BIT6 1DIR
//12 BIT7 1DIR
//13 BIT7 2DIR
//14 BIT6 2DIR

void ADC_init(void);                          // function prototypes
void Ports_init(void);
void TimerA_init(void);
int volts =0;
void main( void )
{
   WDTCTL = WDTPW + WDTHOLD;               // disable watchdog

   Ports_init();                        // init P1 and P2
   ADC_init();                           // init ADC
   TimerA_init();                        // init TimerA

   for (;;)
     __low_power_mode_0();                  // enter sleep mode

}//main

void TimerA_init(void)
{
   TACCR0 = 3125;                     // ADC trigger period ~22 мсек
   TACCTL0 = OUTMOD_4;                     // toggle OUT0 to trigger ADC
   TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR;      // SMCLK/8, up mode, start
}

void Ports_init(void)
{
   P1DIR = 0xFF;                        // configure port for output
   P1OUT = 0;                                    // init port
   P2DIR = 0xFF;                        // configure port for output
   P2SEL = 0;                           // I/O on XTAL pins
   P2OUT = 0;                                  // init port
}

void ADC_init(void)
{
   ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;   // 16 clocks sample-and-hold
   ADC10CTL1 = SHS_2 + CONSEQ_2;            // trigger by TA0
   ADC10AE0  = BIT0;                       // set ADC channel 0
   ADC10CTL0 |= ENC;                     // enable conversion
}

#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void)            // ADC10 ISR
{
   int  volts = ADC10MEM;          // convert ADC into volts
   char led1 = 0;                        // PORT1 leds stati
   char led2 = 0;                        // PORT2 leds stati

    if (volts >= 60)  led1 |= BIT2;         // new led states
    if (volts >= 132) led1 |= BIT3;
    if (volts >= 204) led1 |= BIT4;
    if (volts >= 276) led1 |= BIT5;
    if (volts >= 348) led2 |= BIT0;
    if (volts >= 420) led2 |= BIT1;
    if (volts >= 492) led2 |= BIT2;
    if (volts >= 564) led2 |= BIT3;
    if (volts >= 636) led2 |= BIT4;
    if (volts >= 708) led2 |= BIT5;
    if (volts >= 280) led1 |= BIT6;
    if (volts >= 852) led1 |= BIT7;
    if (volts >= 924) led2 |= BIT7;
    if (volts >= 996) led2 |= BIT6;
   P1OUT = led1;                        // copy led states to ports
   P2OUT = led2;
}


Немного поправил код, без объявленной volts были хаотичные зажигания и пересчитал пороговые напряжения.
Вроде работает. Сейчас спаяю линейку на 14 светиков, попробую поточней откалибровать. Пора разводить плату :)
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Снял коротенькое видео о работе девайса, выкладываю поправленную прошивку.
Если кому-то нужно, выложу чертёж печатки и конечную схему.

http://www.youtube.com/watch?v=-ThdujIcHWI

Спойлер

Код: Выделить всё

#include <msp430g2452.h>

//1 BIT2 1DIR
//2 BIT3 1DIR
//3 BIT4 1DIR
//4 BIT5 1DIR
//5 BIT0 2DIR
//6 BIT1 2DIR
//7 BIT2 2DIR
//8 BIT3 2DIR
//9 BIT4 2DIR
//10 BIT5 2DIR
//11 BIT6 1DIR
//12 BIT7 1DIR
//13 BIT7 2DIR
//14 BIT6 2DIR

void ADC_init(void);                          // function prototypes
void Ports_init(void);
void TimerA_init(void);
int volts =0;
void main( void )
{
   WDTCTL = WDTPW + WDTHOLD;               // disable watchdog

   Ports_init();                        // init P1 and P2
   ADC_init();                           // init ADC
   TimerA_init();                        // init TimerA

   for (;;)
     __low_power_mode_0();                  // enter sleep mode

}//main

void TimerA_init(void)
{
   TACCR0 = 3125;                     // ADC trigger period ~22 мсек
   TACCTL0 = OUTMOD_4;                     // toggle OUT0 to trigger ADC
   TACTL = TASSEL_2 + ID_3 + MC_1 + TACLR;      // SMCLK/8, up mode, start
}

void Ports_init(void)
{
   P1DIR = 0xFF;                        // configure port for output
   P1OUT = 0;                                    // init port
   P2DIR = 0xFF;                        // configure port for output
   P2SEL = 0;                           // I/O on XTAL pins
   P2OUT = 0;                                  // init port
}

void ADC_init(void)
{
   ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;   // 16 clocks sample-and-hold
   ADC10CTL1 = SHS_2 + CONSEQ_2;            // trigger by TA0
   ADC10AE0  = BIT0;                       // set ADC channel 0
   ADC10CTL0 |= ENC;                     // enable conversion
}

#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void)            // ADC10 ISR
{
   int  volts = ADC10MEM;          // convert ADC into volts
   char led1 = 0;                        // PORT1 leds stati
   char led2 = 0;                        // PORT2 leds stati

    if (volts >= 60)  led1 |= BIT2;         // new led states
    if (volts >= 132) led1 |= BIT3;
    if (volts >= 204) led1 |= BIT4;
    if (volts >= 276) led1 |= BIT5;
    if (volts >= 348) led2 |= BIT0;
    if (volts >= 420) led2 |= BIT1;
    if (volts >= 492) led2 |= BIT2;
    if (volts >= 564) led2 |= BIT3;
    if (volts >= 636) led2 |= BIT4;
    if (volts >= 708) led2 |= BIT5;
    if (volts >= 780) led1 |= BIT6;
    if (volts >= 852) led1 |= BIT7;
    if (volts >= 924) led2 |= BIT6;
    if (volts >= 996) led2 |= BIT7;
   P1OUT = led1;                        // copy led states to ports
   P2OUT = led2;
}
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Ser60 »

Поздравляю! А как Вы хотели задействовать ногу 3 МК?
Реклама
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Ser60 писал(а):Поздравляю! А как Вы хотели задействовать ногу 3 МК?

Собирался снять напряжение с батареи или второго настроечного потенца для SPLIT. Но думаю откажусь и повешу 15 светик. К тому же, нужно уменьшать потребление - при всех горящих светиках плата кушает 72 ма, что много. Буду переделывать на индикацию горящей точкой.
Реклама
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Ser60 »

Если это для (переносной) рации, почему просто не индицировать частоту на ЖКИ?
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Ser60 писал(а):Если это для (переносной) рации, почему просто не индицировать частоту на ЖКИ?

Не интересно. Частотомеры на PICe и AVRe уже есть и делал.
Возникла проблема - мигания светодиодов при переходе через пороги АЦП (при медленом вращении потенца). Нужно организовывать гистерезис (только как)?
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Ser60 »

В простейшем случае можно усреднять показания АЦП в кольцевом буфере. Скажем, 4 последних показания. Это существенно уменьшит дребезг. Погуглите на алгоритмы скользящего среднего.
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Ser60 писал(а):В простейшем случае можно усреднять показания АЦП в кольцевом буфере. Скажем, 4 последних показания. Это существенно уменьшит дребезг. Погуглите на алгоритмы скользящего среднего.

Что=то я не могу додуматься как организовать съём и хранение нескольких показаний с АЦП.
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Ser60 »

Надо завести буфер для хранения показаний и переменную где будет храниться индех самого старого элемента (в начале 0). При получении нового значения от АЦП помещать его в буфер по этому индексу и увеличивать индех в
циклическом порядке. Считать сумму элементов в буфере и делить ее на длину буфера.
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Ser60 писал(а):Надо завести буфер для хранения показаний и переменную где будет храниться индех самого старого элемента (в начале 0). При получении нового значения от АЦП помещать его в буфер по этому индексу и увеличивать индех в
циклическом порядке. Считать сумму элементов в буфере и делить ее на длину буфера.


Код: Выделить всё

int i= 0 ;
int summa = 0;
int A[10];            

{
for (i = 0; i < 10; i++)
{
  A[i] = ADC10MEM;
  summa += A[i];
}
volts = summa / 10;

Примерно так?
Вопросы:
1. Как организовать 10 измерений подряд АЦП?
2. Как организовать изменение i по результату измерения АЦП? Это нужно использовать таймер?

Прошу прошения за нубские вопросы, это мой первый опыт работы с МК MSP430.
До этого писал только для промышленных мотороловских контроллеров на асме и Фортране техпроцессы холодной штамповки, и то уже всё позабыл.
Последний раз редактировалось Unrealee Вт дек 04, 2012 00:08:14, всего редактировалось 1 раз.
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Ser60 »

Код после горизонтальной черты поставьте туда где раньше было получение кода АЦП. Никаких многократных исмерений делать не надо. Длину буфера лучше выбирать равной степени 2, в этом случае деление просто реализовать сдвигом.

Спойлер

Код: Выделить всё

int i= 0 ;
int summa = 0;
int A[8];           

----------
summa = summa - A[i] + ADC10MEM;
A[i] = ADC10MEM;
i++;
if (i == 9) i=0;
int adcAverage = summa >> 3;
Unrealee
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Вс дек 02, 2012 21:11:30

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Unrealee »

Можно ещё парочку дурацких вопросов?
1. Получается, что

Код: Выделить всё

{
   ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;   // 16 clocks sample-and-hold
   ADC10CTL1 = SHS_2 + CONSEQ_2;            // trigger by TA0
   ADC10AE0  = BIT0;                       // set ADC channel 0
   ADC10CTL0 |= ENC;                     // enable conversion

}

Непрерывно сканирует напряжение на 2 ножке? Период сканирования задаётся TimerA_init?
2. Нифига не понял как этот код работает

Код: Выделить всё

summa = summa - A[i] + ADC10MEM;
   A[i] = ADC10MEM;
   i++;
   if (i == 9) i=0;
   int adcAverage = summa >> 3;
   volts = adcAverage;
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: Цифровая шкала с LED линейкой на MSP430

Сообщение Ser60 »

1. Да, именно так. Точнее, как только Таймер досчитает до своего верхнего значения (в программе 3125) он инвертирует напряжение на своем (внутреннем) выходе и каждый нарастающий фронт на нем заставляет АЦП начинать новое преобразование, заметьте, что без участия процессора, который все это время спит. Он проснется прерыванием по окончании работы АЦП. Таким образом, период измерений в 2 раза больше периода переполнения таймера.

2. В переменной summa хранится сумма последних 8-ми кодов АЦП. Для подсчета новой суммы после очередного измерения можно добавить это измерение к сумме и вычесть из нее самое старое измерение. Последнее находится под индексом i в массиве. После этого i увеличивается на 1 и указывает на самое старое значение для следующей итерации. Индекс i увеличивается по модулю 8 для реализации кольцевого буфера, т.е. по кругу 0,1,...,7,0,1,...,7. Кстати, я там опечатался и в инструкции
if (i == 9) i=0;
следует производить проверку i на 8. Или еще лучше для эффективности вместо нее написать
i = i & 7;
Ответить

Вернуться в «Разные вопросы по МК»