roboforum.ru

Технический форум по робототехнике.
Текущее время: 01 мар 2025, 13:24

Часовой пояс: UTC + 4 часа




Начать новую тему Ответить на тему  [ Сообщений: 6 ] 
Автор Сообщение
 Заголовок сообщения: Winarv И Int32
СообщениеДобавлено: 17 июн 2010, 16:12 
Не в сети

Зарегистрирован: 17 июн 2010, 16:08
Сообщения: 3
Откуда: Харьков
прог. языки: C/C++, С#, ASP, SQL, PHP, JS
Доброго времени суток. Нужно сделать быстрый вольтметр сетевого напряжения для отслеживания всяких падений. Для этого, как я понимаю, нужно выбрать из периода некоторое количество мгновенных значений напряжения, сложить их квадраты и извлечь из этого корень. Ну или, как вариант, использовать что-то на подобие ad536, которых просто нет в нашем городе, поэтому остановился на первом.

В процессе отладки программы в протеусе(atmega32) столкнулся с тем, что программа сбрасывается при выполнении с 32-битными числами таких операций, как остаток от деления, деление и, наверняка, что-нибудь ещё. Вместо команды "_delay_loop_2(5000)" почему-то также происходит сброс.

Кроме того, мне не удалось завести таймер1 - устанавливаю коэффициенты в TCCR1B, а регистр TCNT1 не увеличивает своего содержания.

Исходник:
Код:
#define   __AVR_ATmega32__   1
#define OSCSPEED   8000000      /* in Hz */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/iom32.h>
#include <avr/delay.h>
#include <avr/wdt.h>
#include <math.h>
#include <stdint.h>

void resetDisplay()
{
   PORTB &= 0x80;
   PORTD &= 0x83;
   PORTB |= 0x1F;
   PORTD |= 0x70;
}

void showDigit(long int* digit)
{
   switch(*digit)
   {
      case 0:
         PORTB &= 0xF2;
         PORTD &= 0x8F;
         break;
      case 1:
         PORTB &= 0xF7;
         PORTD &= 0xBF;
         break;
      case 2:
         PORTB &= 0xF8;
         PORTD &= 0x9F;
         break;
      case 3:
         PORTB &= 0xF1;
         PORTD &= 0x9F;
         break;
      case 4:
         PORTB &= 0xF5;
         PORTD &= 0xAF;
         break;
      case 5:
         PORTB &= 0xF1;
         PORTD &= 0xCF;
         break;
      case 6:
         PORTB &= 0xF0;
         PORTD &= 0xCF;
         break;
      case 7:
         PORTB &= 0xF7;
         PORTD &= 0x8F;
         break;
      case 8:
         PORTB &= 0xF0;
         PORTD &= 0x8F;
         break;
      case 9:
         PORTB &= 0xF1;
         PORTD &= 0x8F;
         break;
   }
}

int wADC = 0;
long int adcData;
int adcFlag = 1;
unsigned int timer = 0;

ISR(SIG_OVERFLOW1)
{
   PORTC = 1;
   adcFlag = 0;
   
   wADC = sqrt(adcData);
   adcData = 0;
   TCNT1 = 0xFD8F;   // 64911
   
   adcFlag = 1;
}

ISR(SIG_ADC)
{
   PORTC = 1;

   if(adcFlag)
   {
      long int adcTemp = ADCW;
      adcTemp *= adcTemp;
      adcData += adcTemp;
   }
   
   ADCSRA |= 0x50;   // 0b01010000
}

int main (void)
{
   adcData = 0;

   PORTB = 0x0;
   PORTC = 0x0;
   PORTD = 0x0;

   DDRB = 0x7F;   // 0b01111111
   DDRC = 0x1;   // 0b00000001
   DDRD = 0x7C;   // 0b01111100
   
   ADMUX = 0;
   ADCSRA = 0xCD;   // 0b11001101
   
   TCCR1A = 0;
   TCCR1B = 7;   // 0b00000111
   TCNT1 = 0xFD8F;   // 64911
   TIFR = 0;
   TIMSK = 0x80;   // 0b10000000
   GIMSK = 0;
   
   sei();
   
   while(1)
   {      
      long int num = wADC;
      long int digit = 0;
      num /= 10.3;
      
      for(int i = 0; i < 2; i++)
      {
         timer = TCNT1;
         resetDisplay();
         
         if(i == 0) PORTB |= 0x40;
         else PORTB |= 0x20;
         
         digit = num % 10;
         num /= 10;
         
         showDigit(&digit);
         
         //_delay_loop_2(5000);
      }
      
      resetDisplay();
      wdt_reset();
   }
}



Помогите, пожалуйста, решить проблемы!

Вложение:
Комментарий к файлу: Проект Протеуса
proteus.rar [29.94 КиБ]
Скачиваний: 0


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Winarv И Int32
СообщениеДобавлено: 17 июн 2010, 17:13 
Не в сети
Site Admin
Аватара пользователя

Зарегистрирован: 09 фев 2006, 15:36
Сообщения: 3339
Откуда: Москва
Skype: vooon341
прог. языки: Python, C, Bash, JavaScript, C++, PHP
ФИО: Владимир Ермаков
Это:
Код:
#define   __AVR_ATmega32__   1
#define OSCSPEED   8000000      /* in Hz */


Сразу выкинуть! -std=gnu99 -mmcu=atmega32 -DF_CPU=8000000UL

Код:
#include <avr/interrupt.h>
-#include <avr/signal.h>
-#include <avr/iom32.h>
-#include <avr/delay.h>
+#include <util/delay.h>
+#include <stdint.h>


showDigit лучше изменить, использовать таблицу:
Код:
#define ARRAY_SIZE(array) ( sizeof(array)/sizeof(array[0]) )
typedef struct {
    uint8_t portb;
    uint8_t portd;
} digit_t;

digit_t digit_table[] = {
    [0] = { 0xf2, 0x8f },
    ...
};

void showDigit(uint8_t digit)
{
    if (digit > ARRAY_SIZE(digit_table))
        return;
    digit_t *ptr = digit_table+digit;
    PORTB &= ptr->portb;
    PORTD &= ptr->portd;
}


Инициализировать так регистры крайне неудобно для сопровождения.
Лучше писать так:
Код:
// TIM 1 Config:
//   Overflow irq
//   Freq: xxx
TCNT1 = 64911;
TCCR1A = _BV(bita)|_BV(bitb)|_BV(bitc);
TCCR1B = _BV(bita)|_BV(bitb)|_BV(bitc);
TIMSK |= _BV(OCIE1);


А пока мне разбираться в этом месиве совершенно не хочется.

Добавлено спустя 5 минут 18 секунд:
И потом, у первого таймера есть прерывания по совпадению и CTC Mode, зачем писать через переполнения?

_________________
Linux user | Firefox user


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Winarv И Int32
СообщениеДобавлено: 17 июн 2010, 17:52 
Не в сети

Зарегистрирован: 27 авг 2008, 10:45
Сообщения: 1981
Откуда: Харьков
прог. языки: С/С++
Да, а программа сбрасывается может быть оттого, что ватчдог активен?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Winarv И Int32
СообщениеДобавлено: 17 июн 2010, 22:10 
Не в сети

Зарегистрирован: 17 июн 2010, 16:08
Сообщения: 3
Откуда: Харьков
прог. языки: C/C++, С#, ASP, SQL, PHP, JS
Vooon, спасибо, после выполнения ваших рекомендаций всё как-то само сразу заработало.

В итоге что-то такое получилось, может пригодится:
Код:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <math.h>
#include <stdint.h>

#define ARRAY_SIZE(array) ( sizeof(array)/sizeof(array[0]) )

typedef struct {
    uint8_t portb;
    uint8_t portd;
} digit_t;

digit_t digit_table[] = {
    [0] = { 0xf2, 0x8f },
    [1] = { 0xf7, 0xbf },
    [2] = { 0xf8, 0x9f },
    [3] = { 0xf1, 0x9f },
    [4] = { 0xf5, 0xaf },
    [5] = { 0xf1, 0xcf },
    [6] = { 0xf0, 0xcf },
    [7] = { 0xf7, 0x8f },
    [8] = { 0xf0, 0x8f },
    [9] = { 0xf1, 0x8f }
};

void showDigit(uint8_t digit)
{
    if (digit > ARRAY_SIZE(digit_table)) return;
    digit_t *ptr = digit_table + digit;
    PORTB &= ptr->portb;
    PORTD &= ptr->portd;
}

void resetDisplay()
{
   PORTB &= 0x80;
   PORTD &= 0x83;
   PORTB |= 0x1F;
   PORTD |= 0x70;
}

int wADC = 0;
long int adcData;
int adcFlag = 1;
unsigned int timer = 0;

ISR(SIG_OUTPUT_COMPARE1A)
{
   PORTC = 1;
   adcFlag = 0;
   
   wADC = sqrt(adcData);
   adcData = 0;
   
   adcFlag = 1;
}

void start_config()
{
   // Ports Config
   PORTB = 0x0;
   PORTC = 0x0;
   PORTD = 0x0;
   DDRB = 0x7F;   // 0b01111111
   DDRC = 0x1;      // 0b00000001
   DDRD = 0x7C;   // 0b01111100
   
   // ADC Config
   //   Freq:   8M/64 = 125000
   //   Pin:    PA0
   //    Int:   true
   //   Start:   true
   //    Enabl:   true
   ADMUX = 0;
   ADCSRA = _BV(ADPS1)|_BV(ADPS2)|_BV(ADIE)|_BV(ADSC)|_BV(ADEN);
   
   // Timer1 Config
   //   Freq:   8M/256 = 31250
   //   OCR1A: 625
   //    Int:   OCR1A
   //    CTC:   true
   TCCR1A = 0;
   TCCR1B = _BV(WGM12)|_BV(CS12);
   TCNT1 = 0;
   TIFR = 0;
   TIMSK = _BV(OCIE1A);
   GIMSK = 0;
   OCR1A = 625;
   
   // RS232 Config
   //   Freq:   9600
   unsigned int BaudRate = 51;
   UBRRH = (unsigned char) (BaudRate>>8);
   UBRRL = (unsigned char) BaudRate;
   UCSRB |= _BV(RXEN)|_BV(TXEN);
   UCSRC |= _BV(UCSZ0)|_BV(UCSZ1)|_BV(URSEL);
   
   sei();
}

ISR(SIG_ADC)
{
   PORTC = 1;

   if(adcFlag)
   {
      long int adcTemp = ADCW;
      adcTemp *= adcTemp;
      adcData += adcTemp;
   }
   
   ADCSRA |= _BV(ADIF)|_BV(ADSC);
}

int main (void)
{
   adcData = 0;
   
   start_config();
   
   while(1)
   {
      if( (UCSRA & _BV(RXCIE)) && (UDR == 'z') )
      {         
         while (!(UCSRA & _BV(UDRE)));
         UDR = (unsigned char) (wADC>>8);
         while (!(UCSRA & _BV(UDRE)));
         UDR = (unsigned char) wADC;
      }
   
      long int num = wADC;
      uint8_t digit = 0;
      num /= 50;
      
      for(int i = 0; i < 2; i++)
      {
         timer = TCNT1;
         resetDisplay();
         
         if(i == 0) PORTB |= 0x40;
         else PORTB |= 0x20;
         
         digit = num % 10;
         num /= 10;
         
         showDigit(digit);
         
         _delay_loop_2(5000);
      }
      
      resetDisplay();
      wdt_reset();
   }
}


Написал софтину для мониторинга сети с помощью этого устройства. Отображает текущее состояние, каждые 5 минут дописывает в файл поминутное состояние. Можно поставить исключения (ниже или выше значений), записывает подробнее, каждые ~20ms. Строит график за день (поминутное состояние). Исходник на C# (используются xCharts, xGauge) в приложении.


Вложения:
uTester.rar [25.34 КиБ]
Скачиваний: 0


Последний раз редактировалось Vooon 17 июн 2010, 22:20, всего редактировалось 1 раз.
[code=cpp]!!!
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Winarv И Int32
СообщениеДобавлено: 17 июн 2010, 22:29 
Не в сети
отсылающий читать курс
Аватара пользователя

Зарегистрирован: 06 ноя 2005, 04:18
Сообщения: 14195
Откуда: Москва
Отлично ! Спасибо. Желательно добавить детектор пиковых значений и записывать зашкаливания. А то в нутри минуты может быть расколбас был в сети а мы не заметим.

_________________
Читайте !


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Winarv И Int32
СообщениеДобавлено: 17 июн 2010, 22:36 
Не в сети

Зарегистрирован: 17 июн 2010, 16:08
Сообщения: 3
Откуда: Харьков
прог. языки: C/C++, С#, ASP, SQL, PHP, JS
avr123.nm.ru писал(а):
Желательно добавить детектор пиковых значений и записывать зашкаливания. А то в нутри минуты может быть расколбас был в сети а мы не заметим.

kolos450 писал(а):
Можно поставить исключения (ниже или выше заданных значений), записывает подробнее, каждые ~20ms.

Я имел в виду, что это уже реализовано.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 6 ] 

Часовой пояс: UTC + 4 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 0


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
phpBB SEO