STM32F103 - генератор синуса

Тед
Offline
Зарегистрирован: 06.11.2017

Я добавил третий таймер, потерял сигнал на A8 и ничего на A9. Сигнал остался на B7


#define SAMPLES 100

#define DEBOUNCE_DELAY 100

#define DEBOUNCE_IDLE 0
#define DEBOUNCE_ACTIVE 1

#include <libmaple/dma.h>

struct debounce_info
{
    int start, state;
    uint16 shift;
}left, right, up, down;

dma_tube_config dma_cfg, dma_cfg2; 

int flag1 = 0;
int flag2 = 0;
int flag3 = 0;  // added

int out1 = PB7;           
int out2 = PA8;
int out3 = PA9;  // added problem !!!

int val1[SAMPLES];
int val2[SAMPLES];
int val3[SAMPLES];  // added

int phasep = PB6;
int phasen = PB5;
int ampp = PB8;
int ampn = PB9;

uint16 shift = 0;

int amp = 20;
int cnt = 0;
int time_track = 0;
float stp = 6.2831/SAMPLES;    
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
timer_dev *dev3 = PIN_MAP[out3].timer_device;  // added
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;
uint8 cc_channel3 = PIN_MAP[out3].timer_channel;  // addet

void fun()
{
    flag1++;
}

void fun2()
{
    flag2++;
}

void timer_conf()
{
  
  timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  timer_dma_enable_req(dev1, cc_channel1);
  timer_set_reload(dev1, 50);
  timer_set_prescaler(dev1, 0);
  
  timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
  timer_dma_set_burst_len(dev2, 1);
  timer_dma_enable_req(dev2, cc_channel2);
  timer_set_reload(dev2, 50);
  timer_set_prescaler(dev2, 0);
  /*added */
  timer_dma_set_base_addr(dev3, TIMER_DMA_BASE_CCR3);
  timer_dma_set_burst_len(dev3, 1);
  timer_dma_enable_req(dev3, cc_channel1);
  timer_set_reload(dev1, 50);
  timer_set_prescaler(dev1, 0);
}

void dma_conf()
{
    dma_init(DMA1);
    /* T4C2 DMA C4 */
    dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val1;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);
    
    /* T1C1 DMA C2 */
    dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val2;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);
    /* #2 added _ T1C1 DMA C3 */
    dma_cfg.tube_dst = &(dev3->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val3;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH3;
    dma_cfg.target_data = 0;

     ret = dma_tube_cfg(DMA1, DMA_CH3, &dma_cfg);
}

void dma_start()
{
  dma_attach_interrupt(DMA1, DMA_CH4, fun);
    
  dma_enable(DMA1, DMA_CH4);
  timer_resume(dev1);
  
  dma_attach_interrupt(DMA1, DMA_CH2, fun2);
    
  dma_enable(DMA1, DMA_CH2);
  timer_resume(dev2);
  /*  added */
  dma_attach_interrupt(DMA1, DMA_CH3, fun2);
    
  dma_enable(DMA1, DMA_CH3);
  timer_resume(dev3);
}

void init_wave()
{
  int i;
  for(i=0;i<SAMPLES;i++)
  {
      val1[i] = 24 + amp * sin(stp * i);
      val2[i] = val1[i];
  }
}

void get_wave(uint16 shift)
{
  int i;
  for(i=1;i<SAMPLES;i++)
  {
      val2[i] = 24 + amp * sin( stp * i + shift * 0.1 * 6.2831 / 360);
  }
}

void setup() {
  int i;
  pinMode(out1, PWM);
  pinMode(out2, PWM);
  /*added */
   pinMode(out3, PWM);
  pinMode(phasep, INPUT);
  pinMode(phasen, INPUT);
  pinMode(ampp, INPUT);
  pinMode(ampn, INPUT);
  
  memset(&left, 0, sizeof(debounce_info));
  memset(&right, 0, sizeof(debounce_info));
  memset(&up, 0, sizeof(debounce_info));
  memset(&down, 0, sizeof(debounce_info));
  
  left.shift = -1;
  right.shift = 1;
  up.shift = 1;
  down.shift = -1;
  
  Serial.begin(9600);

  timer_conf();
  dma_conf();
  dma_start();
  
  init_wave();
  
}

void loop() {
  process_key(digitalRead(phasep), &right);
  process_key(digitalRead(phasen), &left);
  process_key_amp(digitalRead(ampp), &up);
  process_key_amp(digitalRead(ampn), &down);
  delay(80);
}

void process_key(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          shift += k->shift;
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
      break;
  }
}

void process_key_amp(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          amp += (int)k->shift;
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
      break;
  }
}

 

arduino328
Offline
Зарегистрирован: 01.09.2016

Тед пишет:

Синусу необходимо и дополнительно прямоугольник

Ну какой же синус без прямоугольника? :)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

вот тебе вариант с настраиваимой частотой.

Но сдвиг фазы ТОЛЬКО на целое число микросекунд, в гет-вейв() сам посмотришь.

Меандр делается двумя прерываниями из ДМА: полуготовность и готовность. Нужно будет сам разберешься.

Если тебе фаза нужна точнее 1 мкс, то самое лучшее меандр выдавать на неподвижный синус (который на PB7), а двигать PA8 через массив, как раньше было. Иначе нужно городить еще один таймер, а это бред. Но и с этим помогу, если будет минута и желание.

#define F_TIMER   72000000
#define FREQ    900  //частота синуса в герцах

#define SAMPLES ((int)sqrt(F_TIMER / FREQ))
#define T_CNT   ((F_TIMER/FREQ)/SAMPLES) 

#define sin_zero     (T_CNT/2)
#define amp0         (sin_zero/2)
#define max_amp      (sin_zero-1) 
        

#define DEBOUNCE_DELAY 100

#define DEBOUNCE_IDLE 0
#define DEBOUNCE_ACTIVE 1

#include <libmaple/dma.h>
#include <EEPROM.h>

struct debounce_info
{
    int start, state;
    int16 shift;
}left, right, up, down;

dma_tube_config dma_cfg, dma_cfg2;

int flag1 = 0;
int flag2 = 0;

int out1 = PB7;           
int out2 = PA8;
int out3 = PA9;

int * val1 = new int[SAMPLES];
int * val2 = new int[SAMPLES];

int phasep = PB6;
int phasen = PB5;
int ampp = PB8;
int ampn = PB9;

int16 shift = 0;

int amp = amp0;
int cnt = 0;
int time_track = 0;
float stp = 6.2831/SAMPLES;    
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;

void fun()
{
    static uint8_t ff=0;
    flag1++;
  
}

void fun2()
{
  static uint8_t ff=0;
    flag2++;
    digitalWrite(out3,ff=(1-ff));
    
}

void timer_conf()
{
  
  timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  timer_dma_enable_req(dev1, cc_channel1);
  timer_set_reload(dev1, T_CNT);
  timer_set_prescaler(dev1, 0);
  
  timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
  timer_dma_set_burst_len(dev2, 1);
  timer_dma_enable_req(dev2, cc_channel2);
  timer_set_reload(dev2, T_CNT);
  timer_set_prescaler(dev2, 0);
}

void dma_conf()
{
    dma_init(DMA1);
    /* T4C2 DMA C4 */
    dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val1;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);
    
    /* T1C1 DMA C2 */
    dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val2;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_HALF_CMPLT_IE | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);
}

void dma_start()
{
  dma_attach_interrupt(DMA1, DMA_CH4, fun);
    
  dma_enable(DMA1, DMA_CH4);
  timer_resume(dev1);
  
  
  dma_attach_interrupt(DMA1, DMA_CH2, fun2);  
  dma_enable(DMA1, DMA_CH2);
  
  timer_resume(dev2);
}

void init_wave()
{
  int i;
  for(i=0;i<SAMPLES;i++)
  {
      val1[i] = sin_zero + amp * sin(stp * i);
      val2[i] = val1[i];
  }
}

void get_wave(int16 shift)
{
  int delll = (shift*1000000/FREQ)/3600;
  int i;
  //for(i=0;i<SAMPLES;i++)
  //{
  //    val2[i] = sin_zero + amp * sin( stp * i + shift * 0.1 * 6.2831 / 360);
  //}
  if (i) 
    {
     dma_disable(DMA1, DMA_CH2);
     timer_pause(dev2);
  
     delayMicroseconds(i);
 
     dma_enable(DMA1, DMA_CH2);
     timer_resume(dev2);
    } 
}

void setup() {
  int i;
  pinMode(out1, PWM);
  pinMode(out2, PWM);
  pinMode(out3, OUTPUT);

  
  pinMode(phasep, INPUT);
  pinMode(phasen, INPUT);
  pinMode(ampp, INPUT);
  pinMode(ampn, INPUT);
  
  memset(&left, 0, sizeof(debounce_info));
  memset(&right, 0, sizeof(debounce_info));
  memset(&up, 0, sizeof(debounce_info));
  memset(&down, 0, sizeof(debounce_info));
  
  left.shift = -1;
  right.shift = 1;
  up.shift = 1;
  down.shift = -1;
  
  Serial.begin(9600);

  timer_conf();
  dma_conf();
  dma_start();
  
  init_wave();
  EEPROM.read(0, (uint16*)&shift);
  get_wave(shift);
  
}

void loop() {
  /*process_key(digitalRead(phasep), &right);
  process_key(digitalRead(phasen), &left);
  //process_key_amp(digitalRead(ampp), &up);
  process_key_amp(digitalRead(ampn), &down);*/
  delay(80);
  Serial.println(shift);
}

void process_key(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          shift += k->shift;
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
        EEPROM.write(0, shift);
      break;
  }
}

void process_key_amp(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          if (amp<max_amp && amp > 0) amp += (int)k->shift;
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
        
      break;
  }
}

 

Тед
Offline
Зарегистрирован: 06.11.2017

Большое спасибо это много работы  - излучаю. Мой генератор работает на 7 kHz, фазовая точность 0.1 градусов. 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

Большое спасибо это много работы  - излучаю. Мой генератор работает на 7 kHz, фазовая точность 0.1 градусов. 

Ну вот опять  придется обзываться!

1.Ду....нь! Это в формуле у тебя было 0.1,  а в реальности все это съедается. Ты хоть понимаешь как ИМЕННО эта программа генерит синус? Кто тебе это писал? Попроси пояснить,а я не нанимался в коррекционные педагоги. ;)

Я потому и спросил про 1 мкс, что не знаю для чего тебе все это. Какая точность фазы на самом деле нужна? Если ты параметры звукового тракта измеряешь, то 1 мкс - достаточно, если это лабораторное исследование, то хрен его знает.  

2. в первом посте генератор был на 72000000/2000/102=352 Гц.

Не 7 КГц, мля, а 352Гц! В 20 раз меньше.

3. я тебе переписал сразу с преобразованием. Задаешь ТОЛЬКО #define FREQ  ! Остальное она все сама делает.

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

короче так: я, возможно (без обещаний!!!), захочу написать тебе нормальный код бесплатно.

С тебя требуется тут, в этой теме, четко и ясно описать что ты делаешь. Описать своим языком, свою задачу. Не пытаясь что-то говорить про програмирование.

Твоя попытка вставить третий таймер говорит, не то что о улевом, а об отрицательном  уровне подготовки. Поэтому прошу говорить о своей цели.

Тед
Offline
Зарегистрирован: 06.11.2017

Первый вариант - ошибка, поэтому я дал второй вариант. Моя цель - добавить 3 канала - прямоугольные импульсы с той же фазой, что и на A7   

 

 

Тед
Offline
Зарегистрирован: 06.11.2017

Новый код с самого начала не нужно, слишком много работы LM386 работает хорошо, как я уже писал, я хотел заменить его программой.

Тед
Offline
Зарегистрирован: 06.11.2017
LM386. усиление 200.
  раз и от синуса у меня есть прямоугольник
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

я прелагаю сделать прямоугольные синфазно PB7,  а двигать PA8. Поскольку фазу можно двигать как в + так и в - - это проще. Тебе просто в подключении нужно поменять входы.

Короче, пиши, что и для чего ты используешь. Иначе я мозг себе сломаю, что-то объясняя.

==========================================================

Сейчас на моем коде выстави частоту и поиграйся пока с ним.

Завтра расскажешь. Я человек не молодой, мне спать пора.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

Первый вариант - ошибка, поэтому я дал второй вариант. Моя цель - добавить 3 канала - прямоугольные импульсы с той же фазой, что и на A7   

Ты, блин, плохо соображаешь?! Я прошу сказать, что ты делаешь, то есть зачем ты это используешь. А не что от программы хочешь. Твои хотелки - скорее всего полная чушь и решаются без изнасилования STM32.

Меандр синфазно PA8 я тебе УЖЕ сделал,в коде выше. Поиграй с ним пока. Посмотри осцилографом.

Тед
Offline
Зарегистрирован: 06.11.2017

В вашей программе на B8 и B9 ничего нет. Но A8 - имеются очень узкие импульсы. Если бы они были в фазе с оригинальным A8, тогда это было бы хорошо.

Тед
Offline
Зарегистрирован: 06.11.2017

Моя цель - добавить 3 канала 

должно быть - добавить третий канал

Тед
Offline
Зарегистрирован: 06.11.2017
Я проверил вторую версию, есть третий канал, кнопки не работают, 
 поменял A9 на B12, A9 и A10 будет использоваться для Serial Plotter, пытаюсь добавить эту строчку _ Serial.println (sine1, sine2); 
 
Я хочу сделать металлоискатель с минимальным количеством аналоговых частей, следующий в очереди, - AD8302 amplitude/ phase detector - фазометр. Сколько будет стоить чобы его заменить ?
 
Парень, который написал эту программу, знает программирование, но не знает электроники, ему потребовалось много времени, чтобы написать эту программу.
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

Я проверил вторую версию, есть третий канал, кнопки не работают,

Дык они ж закомментированы!

Ты слепой? Я взял код из твоего первого сообщения и добавил меандр и перестройку частоты.

Я не могу понять, ты на код смотришь как на шумерскую клинопись или, все-таки, читаешь его?

Тед
Offline
Зарегистрирован: 06.11.2017

Я псравнял  с моим  ничего не нашел.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Теперь поехали, раз уж появиласьреальная информация.

1. Код это писали долго???!!! Написана херня, с которой тяжело работатьи тяжело модифицировать.

Нет, не безграмотно, по своему забавно, но "из пушки по воробьям".

2. Вопросы:

1. 7000Нц тебе нужно фиксированно или нужно перестраивать?

2. какие выходы тебе нужны? два синуса со смещением фазы и меандр синфазно одному из них, так?

3. Какие регулировки? сечас фаза и амплитуда одного из синусов. Что еще нужно?  Какие у тебя кнопки ? (матрица, просто тактовая на землю или что еще?)

4. Про прием? АЦП у СТМ32 - не сильно хорош в смысле шума Какая чувствительность по фазе и амлитуде тебе нужна.

5. если добавлять прием двух каналов на АЦП и измерение их параметров то код уже никуда не годится. Он сейчас уже почти всю память забил.

У синуса нет смысла держать весь период. Не больше 1/4 периода. все остальное проще пересчитывать на ходу... но если одновременно прием, вместо AD8302, то смотреть на что ресурсов хватит. Это будетзависеть от частоты синуса и количества самплов.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

Я псравнял  с моим  ничего не нашел.

Это про что? Если про кнопки, то коментарий сними с них. Я ими вообще не интересовался.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

сорри за опечатки . дерьмовая резиновая китайская клава на кухне. Половину букв не нажимаетили нажимает не те ;););) Очень она пробел не любит!

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

про синус: если знаешь, то насколько чистый он тебе нужен? Коэфф. гармоник допустимый есть в теории ваших металлоискателей?

Тед
Offline
Зарегистрирован: 06.11.2017

Извините, мой первый пост был ошибкой, о которой я писал, второй хороший - я буду искать

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

Парень, который написал эту программу, знает программирование, но не знает электроники, ему потребовалось много времени, чтобы написать эту программу.

Извини, ОФФТОП, я маразмы и приколы коллекционирую.

А "много" это сколько именно времени?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

Извините, мой первый пост был ошибкой, о которой я писал, второй хороший - я буду искать

Чего искать????

Тед
Offline
Зарегистрирован: 06.11.2017

В моем варианте искажения не делают проблемы, в  твоей версии выглядит  хорошо.

Тед
Offline
Зарегистрирован: 06.11.2017

 Я буду сравнивать  с постом # 2, там кнопки работают

Тед
Offline
Зарегистрирован: 06.11.2017

А "много" это сколько именно времени?

два месяца

b707
Offline
Зарегистрирован: 26.05.2017

wdrakula пишет:

 если добавлять прием двух каналов на АЦП и измерение их параметров то код уже никуда не годится. Он сейчас уже почти всю память забил.

Дракула, с интересом слежу за дискуссией. Позволю замечание на тему "код ужн всю память забил" - скомпилил твой код из сообщения #53 - результат:

Скетч использует 25 020 байт (38%) памяти устройства. 
Всего доступно 65 536 байт.
Глобальные переменные используют 2 104 байт (10%) динамической памяти, 
оставляя 18 376 байт для локальных переменных.

так что вроде места еще навалом? Или я что-то не учел?

компиляция Ардуино ИДЕ 1.6.12, плата STM32F103C8T6

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

b707 пишет:

wdrakula пишет:

 если добавлять прием двух каналов на АЦП и измерение их параметров то код уже никуда не годится. Он сейчас уже почти всю память забил.

Дракула, с интересом слежу за дискуссией. Позволю замечание на тему "код ужн всю память забил" - скомпилил твой код из сообщения #53 - результат:

Скетч использует 25 020 байт (38%) памяти устройства. 
Всего доступно 65 536 байт.
Глобальные переменные используют 2 104 байт (10%) динамической памяти, 
оставляя 18 376 байт для локальных переменных.

так что вроде места еще навалом? Или я что-то не учел?

компиляция Ардуино ИДЕ 1.6.12, плата STM32F103C8T6

 

если ты не заметил, то массивы самплов синусов я сделал динамическими и они не в глобальных теперь. А они и жрут всю память

Тед
Offline
Зарегистрирован: 06.11.2017
Вопросы - ответы
в моей программе все работает правильно, нет памяти для амплитуды (для фазы есть). Частота фиксируется программой в диапазоне от 7 кГц до 15 кГц.
4 кнопки.
4. Про прием? - еще не проверено
5. Один канал приема.
 
Тед
Offline
Зарегистрирован: 06.11.2017

Я буду искать кнопки, подумайте о ph-метре

b707
Offline
Зарегистрирован: 26.05.2017

wdrakula пишет:

если ты не заметил, то массивы самплов синусов я сделал динамическими и они не в глобальных теперь. А они и жрут всю память

Почему не заметил -  заметил. Если взять данные из твоего же скетча, там два массива по sqrt(72MHz/ 900 Hz) сэмплов - то есть два массива по 282 значения - это добавляет всего 1к.

Дисклаймер - Я не спорю, я понять хочу - это правильно или я что напутал

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

вот тебе с кнопками. Моя вина, я пересчет убрал пока проверял.... и так его тебе и кинул. ;)

Как говориться   "и про старушку снимают порнушку"! ;)

#define F_TIMER   72000000
#define FREQ    7000

#define SAMPLES ((int)sqrt(F_TIMER / FREQ))
#define T_CNT   ((F_TIMER/FREQ)/SAMPLES) 

#define sin_zero     (T_CNT/2)
#define amp0         (sin_zero/2)
#define max_amp      (sin_zero-1) 
        

#define DEBOUNCE_DELAY 100

#define DEBOUNCE_IDLE 0
#define DEBOUNCE_ACTIVE 1

#include <libmaple/dma.h>
#include <EEPROM.h>

struct debounce_info
{
    int start, state;
    int16 shift;
}left, right, up, down;

dma_tube_config dma_cfg, dma_cfg2;

int flag1 = 0;
int flag2 = 0;

int out1 = PB7;           
int out2 = PA8;
int out3 = PA9;

int * val1 = new int[SAMPLES];
int * val2 = new int[SAMPLES];

int phasep = PB6;
int phasen = PB5;
int ampp = PB8;
int ampn = PB9;

int16 shift = 0;

int amp = amp0;
int cnt = 0;
int time_track = 0;
float stp = 6.2831/SAMPLES;    
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;

void fun()
{
    static uint8_t ff=0;
    flag1++;
  
}

void fun2()
{
  static uint8_t ff=0;
    flag2++;
    digitalWrite(out3,ff=(1-ff));
    
}

void timer_conf()
{
  
  timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  timer_dma_enable_req(dev1, cc_channel1);
  timer_set_reload(dev1, T_CNT);
  timer_set_prescaler(dev1, 0);
  
  timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
  timer_dma_set_burst_len(dev2, 1);
  timer_dma_enable_req(dev2, cc_channel2);
  timer_set_reload(dev2, T_CNT);
  timer_set_prescaler(dev2, 0);
}

void dma_conf()
{
    dma_init(DMA1);
    /* T4C2 DMA C4 */
    dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val1;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);
    
    /* T1C1 DMA C2 */
    dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val2;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_HALF_CMPLT_IE | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);
}

void dma_start()
{
  dma_attach_interrupt(DMA1, DMA_CH4, fun);
    
  dma_enable(DMA1, DMA_CH4);
  timer_resume(dev1);
  
  
  dma_attach_interrupt(DMA1, DMA_CH2, fun2);  
  dma_enable(DMA1, DMA_CH2);
  
  timer_resume(dev2);
}

void init_wave()
{
  int i;
  for(i=0;i<SAMPLES;i++)
  {
      val1[i] = sin_zero + amp * sin(stp * i);
      val2[i] = val1[i];
  }
}

void get_wave(int16 shift)
{
  int delll = (shift*1000000/FREQ)/3600;
  int i;
  for(i=0;i<SAMPLES;i++)
  {
      //val2[i] = sin_zero + amp * sin( stp * i + shift * 0.1 * 6.2831 / 360);
      val2[i] = sin_zero + amp * sin( stp * i);
  }
  if (i) 
    {
     dma_disable(DMA1, DMA_CH2);
     timer_pause(dev2);
  
     delayMicroseconds(i);
 
     dma_enable(DMA1, DMA_CH2);
     timer_resume(dev2);
    } 
}

void setup() {
  int i;
  pinMode(out1, PWM);
  pinMode(out2, PWM);
  pinMode(out3, OUTPUT);

/*  
  pinMode(phasep, INPUT);
  pinMode(phasen, INPUT);
  pinMode(ampp, INPUT);
  pinMode(ampn, INPUT);
 */
  pinMode(phasep, INPUT_PULLDOWN);
  pinMode(phasen, INPUT_PULLDOWN);
  pinMode(ampp, INPUT_PULLDOWN);
  pinMode(ampn, INPUT_PULLDOWN);
  
  memset(&left, 0, sizeof(debounce_info));
  memset(&right, 0, sizeof(debounce_info));
  memset(&up, 0, sizeof(debounce_info));
  memset(&down, 0, sizeof(debounce_info));
  
  left.shift = -1;
  right.shift = 1;
  up.shift = 1;
  down.shift = -1;
  
  //Serial.begin(9600);

  timer_conf();
  dma_conf();
  dma_start();
  
  init_wave();
  EEPROM.read(0, (uint16*)&shift);
  get_wave(shift);
  
}

void loop() {
  process_key(digitalRead(phasep), &right);
  process_key(digitalRead(phasen), &left);
  process_key_amp(digitalRead(ampp), &up);
  process_key_amp(digitalRead(ampn), &down);
  delay(80);
 // Serial.println(shift);
}

void process_key(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          shift += k->shift;
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
        EEPROM.write(0, shift);
      break;
  }
}

void process_key_amp(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          if ((amp<max_amp) && (amp > 0)) amp += (int)(k->shift);
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
        
      break;
  }
}

 

Тед
Offline
Зарегистрирован: 06.11.2017

прямоугольные импульсы (A9) можно использовать для запуска таймера, чтобы остановить - сигнал от приемника

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

b707 пишет:

wdrakula пишет:

если ты не заметил, то массивы самплов синусов я сделал динамическими и они не в глобальных теперь. А они и жрут всю память

Почему не заметил -  заметил. Если взять данные из твоего же скетча, там два массива по sqrt(72MHz/ 900 Hz) сэмплов - то есть два массива по 282 значения - это добавляет всего 1к.

Дисклаймер - Я не спорю, я понять хочу - это правильно или я что напутал

Если сделать, как ТС хочет еще один канал на таймере, то это еще память, и если принимать два канала, то нужно еще два массива хотя бы по 1000 на прием.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

прямоугольные импульсы (A9) можно использовать для запуска таймера, чтобы остановить - сигнал от приемника

ты прямоугольные проверь! я не смотрел они синфазно или противофазно. переставлять их с А9 можешь куда угодно.

формируются они в fun2()

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тед пишет:

Вопросы - ответы
в моей программе все работает правильно, нет памяти для амплитуды (для фазы есть). Частота фиксируется программой в диапазоне от 7 кГц до 15 кГц.
4 кнопки.
4. Про прием? - еще не проверено
5. Один канал приема.
 

5. а с чем сравнивать будешь? уровень то измерить не проблемма, а фазу нужно сравнивать, так с чем?

Без обид, но ты много тупил, поэтому твой уровень и в электронике не ясен пока.

Понимаешь ли ты, что AD8302 СРАВНИВАЕТ фазы на двух своих входах? а остальное - тупое измерение уровня сигнала, доступное на чем угодно?

Вот я и спрашиваю, фаза относительно чего? в твоем понимании, если без AD8302.

b707
Offline
Зарегистрирован: 26.05.2017

wdrakula пишет:

Если сделать, как ТС хочет еще один канал на таймере, то это еще память, и если принимать два канала, то нужно еще два массива хотя бы по 1000 на прием.

ок понял

Тед
Offline
Зарегистрирован: 06.11.2017
кнопки работают но подругому -  быстро два или три быстрые большие шаги
Оригинал был: для фазы шаг настройки 1/100 от 180 градусов. Время настройки от 0 до 180 градусов 3 минуты. Амплитуда -шаг  30 мВ
Тед
Offline
Зарегистрирован: 06.11.2017
сравниваешь с А8 или A9
A9 - нет нужды в - zero crossing detector
Тед
Offline
Зарегистрирован: 06.11.2017

5. а с чем сравнивать будешь? уровень то измерить не проблемма, а фазу нужно сравнивать, так с чем?

прямоугольные импульсы (A9) можно использовать для запуска таймера, чтобы остановить - сигнал от приемника

Тед
Offline
Зарегистрирован: 06.11.2017

Сейчас шаг для фазы 60 градусов, для амплитуды гдето 100 мв но только 3 шага - сам идиот туда и обратно

Тед
Offline
Зарегистрирован: 06.11.2017

Я снова загрузил , амплитуда регулируется почти как надо, фаза не регулируется.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

У тебя рюсске не родной, штоле?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ok. пробуй пиши. Я - до завтра.

Шабат, самогон и все эти вещи...

Тед
Offline
Зарегистрирован: 06.11.2017

фаза сдвигается большими шагами в одну сторону

Тед
Offline
Зарегистрирован: 06.11.2017

нужно уменьшить шаг настройки амплитуды в 10 раз и записать переменные в ЕЕПРОМ, регулировка фазы не работает.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Так. Вот тебе код с работающими кнопками по фазе и амплттуде.

#define F_TIMER   72000000
#define FREQ    7000

#define SAMPLES ((int)sqrt(F_TIMER / FREQ))
#define T_CNT   ((F_TIMER/FREQ)/SAMPLES) 

#define sin_zero     (T_CNT/2)
#define amp0         (sin_zero/2)
#define max_amp      (sin_zero-1) 
        

#define DEBOUNCE_DELAY 100

#define DEBOUNCE_IDLE 0
#define DEBOUNCE_ACTIVE 1

#include <libmaple/dma.h>
#include <EEPROM.h>

struct debounce_info
{
    int start, state;
    int16 shift;
}left, right, up, down;

dma_tube_config dma_cfg, dma_cfg2;

int flag1 = 0;
int flag2 = 0;

int out1 = PB7;           
int out2 = PA8;
int out3 = PA9;

int * val1 = new int[SAMPLES];
int * val2 = new int[SAMPLES];

int phasep = PB6;
int phasen = PB5;
int ampp = PB8;
int ampn = PB9;

int16 shift = 0;

int amp = amp0;
int cnt = 0;
int time_track = 0;
float stp = 6.2831/SAMPLES;    
int ret = 17;

timer_dev *dev1 = PIN_MAP[out1].timer_device;
timer_dev *dev2 = PIN_MAP[out2].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;
uint8 cc_channel2 = PIN_MAP[out2].timer_channel;

void fun()
{
    static uint8_t ff=0;
    flag1++;
  
}

void fun2()
{
  static uint8_t ff=0;
    flag2++;
    digitalWrite(out3,ff=(1-ff));
    
}

void timer_conf()
{
  
  timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  timer_dma_enable_req(dev1, cc_channel1);
  timer_set_reload(dev1, T_CNT);
  timer_set_prescaler(dev1, 0);
  
  timer_dma_set_base_addr(dev2, TIMER_DMA_BASE_CCR1);
  timer_dma_set_burst_len(dev2, 1);
  timer_dma_enable_req(dev2, cc_channel2);
  timer_set_reload(dev2, T_CNT);
  timer_set_prescaler(dev2, 0);
}

void dma_conf()
{
    dma_init(DMA1);
    /* T4C2 DMA C4 */
    dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val1;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);
    
    /* T1C1 DMA C2 */
    dma_cfg.tube_dst = &(dev2->regs.gen->DMAR);
    dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
    dma_cfg.tube_src = val2;
    dma_cfg.tube_src_size = DMA_SIZE_32BITS;
    
    dma_cfg.tube_nr_xfers = SAMPLES;
    dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_HALF_CMPLT_IE | DMA_CFG_CMPLT_IE;
    
    dma_cfg.tube_req_src = DMA_REQ_SRC_TIM1_CH1;
    dma_cfg.target_data = 0;
    
    ret = dma_tube_cfg(DMA1, DMA_CH2, &dma_cfg);
}

void dma_start()
{
  dma_attach_interrupt(DMA1, DMA_CH4, fun);
    
  dma_enable(DMA1, DMA_CH4);
  timer_resume(dev1);
  
  
  dma_attach_interrupt(DMA1, DMA_CH2, fun2);  
  dma_enable(DMA1, DMA_CH2);
  
  timer_resume(dev2);
}

void init_wave()
{
  int i;
  for(i=0;i<SAMPLES;i++)
  {
      val1[i] = sin_zero + amp * sin(stp * i);
      val2[i] = val1[i];
  }
}

void get_wave(int16 shift)
{
  int delll = (shift*1000000/FREQ)/3600;
  int i;
  for(i=0;i<SAMPLES;i++)
  {
      val1[i] = sin_zero + amp0 * sin( stp * i - shift * 0.1 * 6.2831 / 360);
      val2[i] = sin_zero + amp * sin( stp * i);
  }
  /*
  if (i) 
    {
     dma_disable(DMA1, DMA_CH2);
     timer_pause(dev2);
  
     delayMicroseconds(i);
 
     dma_enable(DMA1, DMA_CH2);
     timer_resume(dev2);
    }
  */   
}

void setup() {
  int i;
  pinMode(out1, PWM);
  pinMode(out2, PWM);
  pinMode(out3, OUTPUT);

/*  
  pinMode(phasep, INPUT);
  pinMode(phasen, INPUT);
  pinMode(ampp, INPUT);
  pinMode(ampn, INPUT);
 */
  pinMode(phasep, INPUT_PULLDOWN);
  pinMode(phasen, INPUT_PULLDOWN);
  pinMode(ampp, INPUT_PULLDOWN);
  pinMode(ampn, INPUT_PULLDOWN);
  
  memset(&left, 0, sizeof(debounce_info));
  memset(&right, 0, sizeof(debounce_info));
  memset(&up, 0, sizeof(debounce_info));
  memset(&down, 0, sizeof(debounce_info));
  
  left.shift = -1;
  right.shift = 1;
  up.shift = 1;
  down.shift = -1;
  
  Serial.begin(57600);

  timer_conf();
  dma_conf();
  dma_start();
  
  init_wave();
  EEPROM.read(0, (uint16*)&shift);
  get_wave(shift);
  
}

void loop() {
  process_key(digitalRead(phasep), &right);
  process_key(digitalRead(phasen), &left);
  process_key_amp(digitalRead(ampp), &up);
  process_key_amp(digitalRead(ampn), &down);
  delay(80);
  Serial.println(shift);
}

void process_key(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          shift += k->shift;
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
        EEPROM.write(0, shift);
      break;
  }
}

void process_key_amp(int val, struct debounce_info *k)
{
  switch(k->state)
  {
    case DEBOUNCE_IDLE:
      if(val == HIGH)
      {
        k->state = DEBOUNCE_ACTIVE;
        k->start = millis();
      }
      break;
        
    case DEBOUNCE_ACTIVE:
      if(val == HIGH)
      {
        if(millis() - k->start > DEBOUNCE_DELAY)
        {
          amp += (int)(k->shift);
          if (amp>max_amp) amp = max_amp;
          if (amp < 1) amp = 1;
          get_wave(shift);
        }
      }
      else
        k->state = DEBOUNCE_IDLE;
        
      break;
  }
}

Теперь про точность регулировок:

Что за каша в твоей голове, и что ты хочешь - ты объяснил, теперь о грустной реальности.

В данный момент, при частоте 7000Гц и частоте самого контроллера в 72 МГц, мы имеем шаг дискретизации в генераторе синуса 1/100 периода и шаг амплитуды тоже 1/100 от максимальной, то есть от 3 вольт.

Это понятно? Понятно ли, что это не свойство программы, а законы физики и математики? Вот это ВАЖНО понять!

то есть шаг амплитуды 30 мВ и точность фазы, при любом шаге в программе, не выше 360/100=3.6 градуса.

Следовательно тебе нужно решить, что ты хочешь улучшить из двух параметров: точность установки фазы или амплитуды?

--------------------

поясню: 72МГц / 7КГц = примерно 10000. Это 100 самплов по 100 единиц. амплитуда при этом способе генерации - целочисленная - от 0 до 50.

Фаза - тут чуть лучше, но синус создается импульсами ШИМа, посмотри картинку на осцилографе., точность фазы после фильтра не выше количества импульсов на период, то есть не больше 0,01 периода, что равно 3.6 гр.

Вот это то, что реально выдается на порту PB7 (вот прямщас снял ;) ), в синус это превращается RC фильтром. По синусу меняется скважность от импульса к импульсу, понятно?

Поскольку произведение числа самплов на на количество отсчетов в самле у нас 10000, то мы можем увеличить одно, только уменьшив другое, это ясно?

================================

Поняв написанное, выскажи свои скорректированные хотелки. Все писать за тебя не стану, пора начинать думать своей головой.

В коде: B7 - не меняет амплитуду, А8 - меняет, А9 - меандр синфазно А8. кнопки работают все четыре.

Тед
Offline
Зарегистрирован: 06.11.2017
Каши у меня  в голове нет только в информации которую передал.
Запрос был; шаг для фазы 0.1 градусов, для амплитуды 1мВ.  Но поучилось как говоришь 3.6 градусов и 2мВ после твоего исправления - поделил амплитуду на 10.
Думаю что это хватит.
То что объяснил, я так и думал сейчас знаю точно.
Смотрю новый код.
Тед
Offline
Зарегистрирован: 06.11.2017

Выглядит хорошо, дальше проверяю.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

на всякий случай, для единообразия...

У тебя Blue pill? Вот такая?

 

и пора бы привести схему своей вундер-штуки ;).

Как ты уже, наверно, понял, тут, на форуме, люди... ну так, мягко, скажем, немного грамотнее тебя ;) ... не обижайся.