Показаны сообщения с ярлыком Coding. Показать все сообщения
Показаны сообщения с ярлыком Coding. Показать все сообщения

среда, 23 октября 2013 г.

Как писать передаточные функции на Си (Converting Transfer Functions to C Code)

http://www.slideshare.net/DelftOpenEr/ch1-9097263

EMBEDDED CONTROL

- if a feedback control function is to be implemented in software the transfer function can be converted to a C subroutine.
- the method shown here is crude - more mature methods use the z-transforms
- consider the implementation of the following control function as a subroutine.
Figure 8.35 Converting Transfer Functions to C Code
http://engineeronadisk.com/V2/book_modelling/engineeronadisk-76.html

суббота, 12 октября 2013 г.

AVR - как избавиться от чисел с плавающей точкой

Одно из сильных ограничений AVR (на платформе MCS51 это сказывается не так) - быстрый расход памяти при написании программ на Си.
Что поделаешь, за удобства Си и скорость RISC надо платить. Еще больший соблазн - использование для вычислений (например, при измерении напряжений с помощью ADC) чисел float(числа с плавающей запятой). Несмотря на то, что эти вычисления не точны, их слишком просто и удобно применять - можно делить и умножать, не задумываясь о переполнении, и легко представлять результаты вычисления в формате, понятном человеку.
Но плата за float слишком высока - линкер добавляет код библиотек математики, и память программ кончается очень быстро. Другое ограничение - вычисления с float выполняются слишком медленно (если конечно не используется аппаратный перемножитель типа [1]). Если нет возможности реализовать алгоритм программы с применением чисел float (из-за вышеуказанных ограничений по объему кода и скорости), одним из вариантов решения проблемы является переход на числа сфиксированной запятой. Их математические операции (вычитание, сложение, деление, умножение) ничем не отличаются от математических операций с простыми целыми числами, код получается компактный и быстрый.
Число с фиксированной запятой (обычно байт или слово из двух байт) состоит из целой части(находится в старших битах 8 или 16-разрядного числа) и дробной части (находится в младших битах). Пример числа с фиксированной запятой указан на рисунке, с разрядностью в 8 бит (1 байт).


EVR-LAB.PRO

Сайт о электромобилях. (БМС Одесса)

пятница, 4 октября 2013 г.

Программатор AVR USB на Atmega8

Источник http://www.getchip.net/posts/040-uartrs-232-to-usb-prostojj-preobrazovatel/

Наконец-то закончились праздники, и пришло время чего-нибудь сделать.
Начнем, пожалуй, с необходимого устройства, облегчающего жизнь рядового электронщика – устройства связи с компьютером. Это нужно для того, чтобы передать данные в компьютер (температура с датчиков, положение дверей, частота вращения двигателя, таблица значений с регистратора …) или принять данные из компьютера (таблицы значений для вычислений, настоечные данные для устройств, новая прошивка для загрузчика…). Для отладки нового устройства (посмотреть что там, в мозгах микроконтроллера, происходит) вообще незаменимая вещь.
Как Вы знаете, существует множество интерфейсов, посредством которых микроконтроллер может общаться с внешним миром. Но если речь идет о связи с компьютером – вне конкуренции интерфейс RS-232 (COM порт). Причина – простота работы с портом со стороны компьютера и наличие большого количества программ для этого предназначенных. Кроме того, почти в каждом микроконтроллере есть аппаратно поддерживаемый интерфейс USART (это тот-же RS-232, только с напряжениями 0 – 5v), что делает процесс связи легко реализуемым.
Для того, чтобы привести уровни сигнала микроконтроллерного USART к уровням COM порта компьютера нужно собрать несложный преобразователь (например, на МАХ232), но можно пойти по более интересному пути
Более интересный путь  - собрать преобразователь UART to USB. При этом USB порт воспринимается компьютером как виртуальный COM порт. В этом случае мы убиваем сразу несколько зайцев:
– USB порт есть в любом компьютере (хотя COM порт встречается еще довольно часто, но на ноутбуках его уже нет);
– как оказалось преобразователь UART to COM(RS-232) сделать гораздо сложнее, чем UART to USB (два раза делал программатор для СОМ порта с преобразователем МАХ232 – оба раза неудачно);
– если подключать преобразователь через USB хаб, то мы получаем сразу несколько виртуальных COM портов на одном USB, плюс безопасность для компьютера, так как хаб выступает в роли буфера.
Вот схема преобразователя UART to USB.
Схема преобразователя UART - USB

Сразу честно признаюсь – это не мое устройство. Взята данная схема с сайта  www.recursion.jp/avrcdc/ . Причина, по которой я ее здесь привожу – это простота схемы и дешевизна изготовления. Собрать схему довольно просто (можно даже на макете).
Внешний вид преобразователя UART to USB
Плата целяком
Готовое устройство я выполнил в форме «флешки» для того, чтобы удобней было пользоваться в «полевых» условиях. Для большего комфорта можно взять USB удлинитель, одним разъемом прицепить к компьютеру, во второй вставить нашу «флешку-преобразователь» и получим мобильное устройство, которое можно без проблем подключить к любой схеме.

пятница, 13 сентября 2013 г.

Программирование множества кнопок

http://www.adafruit.com/blog/2009/10/20/example-code-for-multi-button-checker-with-debouncing/
#define DEBOUNCE 10  // button debouncer, how many ms to debounce, 5+ ms is usually plenty

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {14, 15, 16, 17, 18, 19}; // the analog 0-5 pins are also known as 14-19
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'currently pressed' 
byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

void setup() {
  byte i;
  
  // set up serial port
  Serial.begin(9600);
  Serial.print("Button checker with ");
  Serial.print(NUMBUTTONS, DEC);
  Serial.println(" buttons");

  // pin13 LED
  pinMode(13, OUTPUT);
 
  // Make input & enable pull-up resistors on switch pins
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }
}

void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  static long lasttime;
  byte index;

  if (millis() < lasttime) {
     // we wrapped around, lets just try again
     lasttime = millis();
  }
  
  if ((lasttime + DEBOUNCE) > millis()) {
    // not enough time has passed to debounce
    return; 
  }
  // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  lasttime = millis();
  
  for (index = 0; index < NUMBUTTONS; index++) {
    justpressed[index] = 0;       // when we start, we clear out the "just" indicators
    justreleased[index] = 0;
     
    currentstate[index] = digitalRead(buttons[index]);   // read the button
    
    /*     
    Serial.print(index, DEC);
    Serial.print(": cstate=");
    Serial.print(currentstate[index], DEC);
    Serial.print(", pstate=");
    Serial.print(previousstate[index], DEC);
    Serial.print(", press=");
    */
    
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
  }
}


void loop() {
  check_switches();      // when we check the switches we'll get the current state
  
  for (byte i = 0; i < NUMBUTTONS; i++) {
    if (justpressed[i]) {
      Serial.print(i, DEC);
      Serial.println(" Just pressed"); 
      // remember, check_switches() will CLEAR the 'just pressed' flag
    }
    if (justreleased[i]) {
      Serial.print(i, DEC);
      Serial.println(" Just released");
      // remember, check_switches() will CLEAR the 'just pressed' flag
    }
    if (pressed[i]) {
      Serial.print(i, DEC);
      Serial.println(" pressed");
      // is the button pressed down at this moment
    }
  }
}
 
 
#define DEBOUNCE 10  // button debouncer, how many ms to debounce, 5+ ms is usually plenty

// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {14, 15, 16, 17, 18, 19}; // the analog 0-5 pins are also known as 14-19
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'currently pressed' 
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

void setup() {
  byte i;
  
  // set up serial port
  Serial.begin(9600);
  Serial.print("Button checker with ");
  Serial.print(NUMBUTTONS, DEC);
  Serial.println(" buttons");

  // pin13 LED
  pinMode(13, OUTPUT);
 
  // Make input & enable pull-up resistors on switch pins
  for (i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }

  // Run timer2 interrupt every 15 ms 
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;

}

SIGNAL(TIMER2_OVF_vect) {
  check_switches();
}

void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  static long lasttime;
  byte index;

  if (millis() < lasttime) {
     // we wrapped around, lets just try again
     lasttime = millis();
  }
  
  if ((lasttime + DEBOUNCE) > millis()) {
    // not enough time has passed to debounce
    return; 
  }
  // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  lasttime = millis();
  
  for (index = 0; index < NUMBUTTONS; index++) {
     
    currentstate[index] = digitalRead(buttons[index]);   // read the button
    
    /*     
    Serial.print(index, DEC);
    Serial.print(": cstate=");
    Serial.print(currentstate[index], DEC);
    Serial.print(", pstate=");
    Serial.print(previousstate[index], DEC);
    Serial.print(", press=");
    */
    
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    }
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
  }
}


void loop() {
  for (byte i = 0; i < NUMBUTTONS; i++) {
    if (justpressed[i]) {
      justpressed[i] = 0;
      Serial.print(i, DEC);
      Serial.println(" Just pressed"); 
      // remember, check_switches() will CLEAR the 'just pressed' flag
    }
    if (justreleased[i]) {
      justreleased[i] = 0;
      Serial.print(i, DEC);
      Serial.println(" Just released");
      // remember, check_switches() will CLEAR the 'just pressed' flag
    }
    if (pressed[i]) {
      Serial.print(i, DEC);
      Serial.println(" pressed");
      // is the button pressed down at this moment
    }
  }
}