Geiger con ARM + OLED

Avatar utente
rberna
Messaggi: 8
Iscritto il: 09/04/2019, 11:39
Località: Correggio
Contatta:

Geiger con ARM + OLED

Messaggio da rberna » 11/04/2019, 20:52

Ciao,

sono in attesa di un tubo STS-5, dicono equivalente a SBM-20..

La mia idea, sicuramente poco originale, è quella di utilizzare un micro ARM (sono abituato ai STM32F...) sia per generare la 400V che per visualizzare i conteggi su un piccolo OLED 64x48 pixel.

Per i 400V stavo pensando a un flyback, oppure 2x boost in serie, tutto gestito dal micro (più mosfet, ovvio). Molto più divertente che usare un chip flyback :-)

Il micro è già montato su una scheda Nucleo (pensavo la F031).

Alimentazione batteria piatta Li, con caricabatterie 5V USB.

Spero di aggiornarvi presto

Ciao



Avatar utente
marconmeteo
Moderatore
Messaggi: 4336
Iscritto il: 08/10/2015, 21:20
Località: Marcon (VE)
Contatta:

Re: Geiger con ARM + OLED

Messaggio da marconmeteo » 11/04/2019, 21:41

Bè non è affatto poco originale, di solito quelli visti in giro (pure un paio che ho realizzato io) utilizzano la piattaforma Arduino o cloni, quindi attendiamo sviluppi...
Ti chiedo solo un'info: per l'HV (ovvero i 400 volt), parli di gestirla dal micro, quindi utilizzando un'uscita pwm seguita da circuito Mosfet come citi?


[External Link Removed for Guests]

"Due cose sono infinite: l'universo e la stupidità umana, ma riguardo all'universo ho ancora dei dubbi" - Albert Einstein


IU3ARP

Avatar utente
rberna
Messaggi: 8
Iscritto il: 09/04/2019, 11:39
Località: Correggio
Contatta:

Re: Geiger con ARM + OLED

Messaggio da rberna » 11/04/2019, 22:16

[Local Link Removed for Guests] ha scritto: [Local Link Removed for Guests]
11/04/2019, 21:41
Bè non è affatto poco originale, di solito quelli visti in giro (pure un paio che ho realizzato io) utilizzano la piattaforma Arduino o cloni, quindi attendiamo sviluppi...
Ti chiedo solo un'info: per l'HV (ovvero i 400 volt), parli di gestirla dal micro, quindi utilizzando un'uscita pwm seguita da circuito Mosfet come citi?
Allora l'idea iniziale era di utilizzare un toroide, ma prima volevo provare un trasformatore già fatto, flyback da alimentatore USB da rete, ne ho proprio qui uno che ha 11 mm di lato. Ovviamente il secondario diventa il primario (alimentato dalla batteria al litio (2.8-4.2V) e viceversa. L'accoppiamento non sarà dei migliori ma parliamo di un alimentatore da 100mW massimi in uscita. IL primario sarà attivato da un NMOS logic level, pilotato direttamente dal micro tramite PWM. E' da decidere se il controllo sarà fatto variando il PWM, o più semplicemente con il metodo pulse-skip, cioè spengo il PWM quando sono a livello, e lo accendo quando scendo. il micro ha dentro due comparatori analogici che possono fare al caso. Stranamente non è possibile collegare il Vref interno ai due comparatori, che hanno tutti i pin portati all'esterno. Credo però che il Vref sia disponbile esternamente (da verificare). Vorrei stare più basso possibile di frequenza di switching, ma dipende dal minimo impulso PWM che riesco a generare (e ad accendere il MOS, i pin del micro hanno correnti misere, confido però in un MOS con Qc bassissima).

Lo scopo è: ridurre al minimo i componenti hardware utilizzando quanto più possibile il micro. Peccato che col flyback servirà un minimo di snubber sul primario.

Altra idea, poco efficiente ma molto "silenziosa": generare una sinusoide a qualche kHz con il micro (molto facile se hai un DAC), buffer a transistor o MOS,
trasformatore elevatore, rettifica (e controreazione ovviamente per la regolazione di tensione).



Avatar utente
eliocor
Senior
Messaggi: 430
Iscritto il: 10/10/2015, 23:28
Località: Europe
Contatta:

Re: Geiger con ARM + OLED

Messaggio da eliocor » 12/04/2019, 1:09

dai una occhiata a questo progetto: possiedo tutti i file del progetto (schemi elettrici/firmware/...) quando erano ancora pubblici.
[External Link Removed for Guests]
sono quasi 400MB di archivio (2016/03/08). Magari te lo metto a disposizione.
Il progetto utilizza un STM32 low power e la generazione della alta tensione è fatta in modo molto semplice....
SCH.pdf
Non hai i permessi necessari per visualizzare i file allegati in questo messaggio.


٩(•̮̮̃•̃)۶ - Excusatio non petita, accusatio manifesta

Avatar utente
rberna
Messaggi: 8
Iscritto il: 09/04/2019, 11:39
Località: Correggio
Contatta:

Re: Geiger con ARM + OLED

Messaggio da rberna » 12/04/2019, 9:56

[Local Link Removed for Guests] ha scritto: [Local Link Removed for Guests]
12/04/2019, 1:09
dai una occhiata a questo progetto: possiedo tutti i file del progetto (schemi elettrici/firmware/...) quando erano ancora pubblici.
[External Link Removed for Guests]
sono quasi 400MB di archivio (2016/03/08). Magari te lo metto a disposizione.
Il progetto utilizza un STM32 low power e la generazione della alta tensione è fatta in modo molto semplice....

SCH.pdf
In pratica esattamente quello che avevo in mente :-(

Flyback non isolato con sensing di tensione non sui 400V ma sulla parte divisa dal trasformatore 1:10, quindi circa 40V. HVdetect va al comparatore interno del micro, quindi immagino la regolazione sia on/off. Ho qualche perplessità sulla R27 22 ohm, riduce l'efficienza e quindi vanifica il sensing fatto sulla 40V invece che sulla 400V..

Se hai i files, mi farebbe piacere riceverli, se puoi con wetransfer o altro.

Grazie comunque!



Avatar utente
eliocor
Senior
Messaggi: 430
Iscritto il: 10/10/2015, 23:28
Località: Europe
Contatta:

Re: Geiger con ARM + OLED

Messaggio da eliocor » 12/04/2019, 23:49

Beh, dato che la copia dei file è stata fatta quando gli stessi erano di pubblico dominio, posso anche lasciarli a disposizione di tutti....
Qui puoi trovare ciò che ti interessa:
[External Link Removed for Guests]
in caso tu addottassi soluzioni prese dal progetto, provvedi a riconoscere al progettista i propri diritti/riconoscimenti!


٩(•̮̮̃•̃)۶ - Excusatio non petita, accusatio manifesta

Avatar utente
rberna
Messaggi: 8
Iscritto il: 09/04/2019, 11:39
Località: Correggio
Contatta:

Re: Geiger con ARM + OLED

Messaggio da rberna » 14/04/2019, 22:09

[Local Link Removed for Guests] ha scritto: [Local Link Removed for Guests]
12/04/2019, 23:49
Beh, dato che la copia dei file è stata fatta quando gli stessi erano di pubblico dominio, posso anche lasciarli a disposizione di tutti....
Qui puoi trovare ciò che ti interessa:
[External Link Removed for Guests]
in caso tu addottassi soluzioni prese dal progetto, provvedi a riconoscere al progettista i propri diritti/riconoscimenti!
Grazie, anche se in russo qualcosa è comprensibile ;-)



Avatar utente
eliocor
Senior
Messaggi: 430
Iscritto il: 10/10/2015, 23:28
Località: Europe
Contatta:

Re: Geiger con ARM + OLED

Messaggio da eliocor » 14/04/2019, 23:39

dai, non fare lo schizzinoso: è facilmente accessibile e se qualcosa non ti è chiara, google translate (meglio ancora yandex) suppliscono per il resto!
Poi uno schema elettrico mica ha bisogno di traduzione!


٩(•̮̮̃•̃)۶ - Excusatio non petita, accusatio manifesta

Avatar utente
rberna
Messaggi: 8
Iscritto il: 09/04/2019, 11:39
Località: Correggio
Contatta:

Re: Geiger con ARM + OLED

Messaggio da rberna » 14/04/2019, 23:47

Certo per lo schema..ma hai provato a leggere il sorgente in C? Comunque va benissimo :-)



Avatar utente
eliocor
Senior
Messaggi: 430
Iscritto il: 10/10/2015, 23:28
Località: Europe
Contatta:

Re: Geiger con ARM + OLED

Messaggio da eliocor » 15/04/2019, 7:02

Come ho precedentemente scritto, non lo vedo un problema per almeno due ragioni:
- pur non avendo mai studiato il russo, conosco i caratteri cirillici e la loro traslitterazione (moltissime parole tecniche russe hanno radici latine o greche)
- esistono traduttori online che funzionano ragionevolmente
ecco prima l'originale e poi la traduzione dei commenti con yandex (notare che nel codice i nomi delle variabili sono tutti in inglese)

Codice: [Local Link Removed for Guests]

#include <stdio.h>
#include <stdint.h>
#include "STM32L1xx.h"          // Device header

#include "main.h"


uint16_t key;                   // массив нажатых кнопок [012]
uint32_t ix;
uint32_t ix_update;

uint16_t Detector_massive[Detector_massive_pointer_max + 1];
uint32_t ram_Doze_massive[doze_length + 1];     // 1 ячейка = 10 минут, на протяжении суток
uint32_t ram_max_fon_massive[doze_length + 1];  // 1 ячейка = 10 минут, на протяжении суток
uint16_t USB_maxfon_massive_pointer = 0;
uint16_t USB_doze_massive_pointer = 0;
uint16_t current_pulse_count = 0;
uint8_t pump_count = 0;
uint8_t Pump_on_alarm_count = 0;
uint32_t Doze_day_count = 0;
uint32_t Doze_week_count = 0;
uint32_t Doze_hour_count = 0;
uint32_t Doze_month_count = 0;
uint32_t Doze_2month_count = 0;
uint32_t Max_fon = 0;
uint8_t main_menu_stat = 1;
uint16_t Detector_massive_pointer = 0;
uint8_t auto_speedup_factor = 0;
uint32_t USB_not_active = 0;
uint32_t last_count_pump_on_impulse = 0;
FunctionalState pump_on_impulse = DISABLE;
uint32_t menu_select = 0;
#ifdef debug
uint32_t debug_wutr = 0;
#endif
FunctionalState enter_menu_item = DISABLE;
uint8_t screen = 1;
uint8_t stat_screen_number = 0;
uint16_t pump_counter_avg_impulse_by_1sec[2];
uint32_t fon_level = 0;
FunctionalState poweroff_state = DISABLE;
FunctionalState hidden_menu = DISABLE;
FunctionalState Pump_on_alarm = DISABLE;

uint32_t unlock_0_serial = 0;
uint32_t unlock_1_serial = 0;
uint32_t unlock_2_serial = 0;
uint32_t unlock_3_serial = 0;

uint32_t working_days = 0;

uint32_t madorc_impulse = 0;

uint32_t Detector_AB_massive[15];       // 1 минута, интервалами по 4 сек
uint32_t AB_fon;                // Фон Альфа-Бета


FunctionalState Sound_key_pressed = DISABLE;

DataUpdateDef DataUpdate;
ADCDataDef ADCData;
SettingsDef Settings;
AlarmDef Alarm;
PowerDef Power;
#ifdef debug
WakeupDef Wakeup;
#endif


/////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000);

  set_msi();
#ifndef debug
  DBGMCU_Config(DBGMCU_SLEEP | DBGMCU_STANDBY | DBGMCU_STOP, DISABLE);
#endif

  set_bor();
  Power.sleep_now = DISABLE;

  DataUpdate.Need_erase_flash = ENABLE;

  Settings.Geiger_voltage = 360;        // Напряжение на датчике 360 вольт
  Settings.Pump_Energy = 350;   // энергия накачки 350 мТл
  DataUpdate.current_flash_page = 0;

  io_init();                    // Инициализация потров МК

  eeprom_write_default_settings();      // Проверка, заполнен ли EEPROM
  eeprom_read_settings();       // Чтение настроек из EEPROM
  screen = 1;
  AB_fon = 0;
  Power.USB_active = DISABLE;
  Power.sleep_time = Settings.Sleep_time;
  Power.Display_active = ENABLE;

  ADCData.DAC_voltage_raw = 0x4FD;

  dac_init();
  comp_init();
  comp_on();
  timer9_Config();              // Конфигурируем таймер накачки        
  timer10_Config();
  tim2_Config();
  sound_activate();
  delay_ms(100);
  sound_deactivate();
//--------------------------------------------------------------------
  RTC_Config();                 // Конфигурируем часы с нуля
//--------------------------------------------------------------------
// инициализация дисплея
//--------------------------------------------------------------------
  delay_ms(50);                 // подождать установки напряжения
  display_on();
  LcdInit();
  LcdClear();
//--------------------------------------------------------------------
  adc_init();
  delay_ms(100);
  adc_calibration();
  delay_ms(10);
//--------------------------------------------------------------------
  EXTI8_Config();
#ifdef version_401
  EXTI9_Config();
#endif
  EXTI3_Config();
  EXTI4_Config();
  EXTI6_Config();

  DataUpdate.Need_batt_voltage_update = ENABLE;

  if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6))
    hidden_menu = ENABLE;       // Открытие сервисных пунктов меню

  delay_ms(500);                // подождать установки напряжения

  while (1)
/////////////////////////////////
  {
    //if(DataUpdate.RTC_tick_update==ENABLE)        RTC_tick_processing();
    if(DataUpdate.Need_fon_update == ENABLE)
      geiger_calc_fon();
    if(key > 0)
      keys_proccessing();
    if(DataUpdate.Need_batt_voltage_update)
      adc_check_event();

    ////////////////////////////////////////////////////


    if((Power.sleep_time > 0) && (!Power.Display_active))
      sleep_mode(DISABLE);      // Если дисплей еще выключен, а счетчик сна уже отсчитывает, поднимаем напряжение и включаем дисплей

    if(Power.Display_active)
    {
      if(Power.sleep_time == 0 && !Alarm.Alarm_active)
        sleep_mode(ENABLE);     // Счетчик сна досчитал до нуля, а дисплей еще активен, то выключаем его и понижаем напряжение
      if(DataUpdate.Need_display_update == ENABLE)
      {
        DataUpdate.Need_display_update = DISABLE;
        LcdClear_massive();
        if(screen == 1)
          main_screen();
        if(screen == 2)
          menu_screen();
        if(screen == 3)
          stat_screen();
      }
///////////////////////////////////////////////////////////////////////////////
    }
#ifdef version_401
    if((!Power.USB_active) && (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9)))
    {
      usb_activate(0x0);        // Если питание USB начало подаваться включаем USB
    }
#endif

    if(!Power.USB_active)       // если USB не активен, можно уходить в сон
    {
      if(current_pulse_count < 30)      // Если счетчик не зашкаливает, то можно уйти в сон
      {
        //if(DataUpdate.RTC_tick_update==ENABLE)        RTC_tick_processing();

        if(!Power.Pump_active && !Power.Sound_active)
        {
//#ifndef debug
          PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); // Переходим в сон
//#endif
#ifdef debug
          Wakeup.total_wakeup++;
          DataUpdate.Need_display_update = ENABLE;
#endif

        } else
        {
          PWR_EnterSleepMode(PWR_Regulator_ON, PWR_SLEEPEntry_WFI);
#ifdef debug
          Wakeup.total_wakeup++;
          DataUpdate.Need_display_update = ENABLE;
#endif
        }
        //if(DataUpdate.RTC_tick_update==ENABLE)        RTC_tick_processing();
      }
    } else
      USB_work();               // если USB активен, попробовать передать данные
#ifdef debug
    Wakeup.total_cycle++;
    DataUpdate.Need_display_update = ENABLE;
#endif

  }
/////////////////////////////////////////////////////////////////////////////// 
}

Codice: [Local Link Removed for Guests]

#include <stdio.h>
#include <stdint.h>
#include "STM32L1xx.h" // Device header

#include "main.h"


uint16_t key; // array of pressed buttons [012]
uint32_t ix;
uint32_t ix_update;

uint16_t Detector_massive[Detector_massive_pointer_max + 1];
uint32_t ram_Doze_massive[doze_length + 1]; // 1 cell = 10 minutes, during the day
uint32_t ram_max_fon_massive[doze_length + 1]; // 1 cell = 10 minutes, during the day
uint16_t USB_maxfon_massive_pointer = 0;
uint16_t USB_doze_massive_pointer = 0;
uint16_t current_pulse_count = 0;
uint8_t pump_count = 0;
uint8_t Pump_on_alarm_count = 0;
uint32_t Doze_day_count = 0;
uint32_t Doze_week_count = 0;
uint32_t Doze_hour_count = 0;
uint32_t Doze_month_count = 0;
uint32_t Doze_2month_count = 0;
uint32_t Max_fon = 0;
uint8_t main_menu_stat = 1;
uint16_t Detector_massive_pointer = 0;
uint8_t auto_speedup_factor = 0;
uint32_t USB_not_active = 0;
uint32_t last_count_pump_on_impulse = 0;
FunctionalState pump_on_impulse = DISABLE;
uint32_t menu_select = 0;
#ifdef debug
uint32_t debug_wutr = 0;
#endif
FunctionalState enter_menu_item = DISABLE;
uint8_t screen = 1;
uint8_t stat_screen_number = 0;
uint16_t pump_counter_avg_impulse_by_1sec[2];
uint32_t fon_level = 0;
FunctionalState poweroff_state = DISABLE;
FunctionalState hidden_menu = DISABLE;
FunctionalState Pump_on_alarm = DISABLE;

uint32_t unlock_0_serial = 0;
uint32_t unlock_1_serial = 0;
uint32_t unlock_2_serial = 0;
uint32_t unlock_3_serial = 0;

uint32_t working_days = 0;

uint32_t madorc_impulse = 0;

uint32_t Detector_AB_massive[15]; // 1 minute, 4 sec intervals
uint32_t AB_fon; // alpha-Beta Background


FunctionalState Sound_key_pressed = DISABLE;

DataUpdateDef DataUpdate;
ADCDataDef ADCData;
SettingsDef Settings;
AlarmDef Alarm;
PowerDef Power;
#ifdef debug
WakeupDef Wakeup;
#endif


/////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000);

  set_msi();
#ifndef debug
  DBGMCU_Config(DBGMCU_SLEEP | DBGMCU_STANDBY | DBGMCU_STOP, DISABLE);
#endif

  set_bor();
  Power.sleep_now = DISABLE;

  DataUpdate.Need_erase_flash = ENABLE;

  Settings.Geiger_voltage = 360; // sensor Voltage 360 volts
  Settings.Pump_Energy = 350; // pumping energy 350 MT
  DataUpdate.current_flash_page = 0;

  io_init(); // Initialize potrov MK

  eeprom_write_default_settings(); // Check if EEPROM is full
  eeprom_read_settings(); // Read settings from EEPROM
  screen = 1;
  AB_fon = 0;
  Power.USB_active = DISABLE;
  Power.sleep_time = Settings.Sleep_time;
  Power.Display_active = ENABLE;

  ADCData.DAC_voltage_raw = 0x4FD;

  dac_init();
  comp_init();
  comp_on();
  timer9_Config(); // Configurable timer pump        
  timer10_Config();
  tim2_Config();
  sound_activate();
  delay_ms(100);
  sound_deactivate();
//--------------------------------------------------------------------
  RTC_Config(); // Configure clock from scratch
//--------------------------------------------------------------------
// display initialization
//--------------------------------------------------------------------
  delay_ms(50); // wait for voltage setting
  display_on();
  LcdInit();
  LcdClear();
//--------------------------------------------------------------------
  adc_init();
  delay_ms(100);
  adc_calibration();
  delay_ms(10);
//--------------------------------------------------------------------
  EXTI8_Config();
#ifdef version_401
  EXTI9_Config();
#endif
  EXTI3_Config();
  EXTI4_Config();
  EXTI6_Config();

  DataUpdate.Need_batt_voltage_update = ENABLE;

  if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6))
    hidden_menu = ENABLE; // Open service menu items

  delay_ms(500); // wait for voltage setting

  while (1)
/////////////////////////////////
  {
    //if(DataUpdate.RTC_tick_update== = ENABLE) RTC_tick_processing();
    if(DataUpdate.Need_fon_update == ENABLE)
      geiger_calc_fon();
    if(key > 0)
      keys_processing();
    if(DataUpdate.Need_batt_voltage_update)
      adc_check_event();

    ////////////////////////////////////////////////////


    if((Power.sleep_time > 0) && (!Power.Display_active))
      sleep_mode(DISABLE); // If the display is still off, and the sleep counter is already counting, raise the voltage and turn on the display

    if(Power.Display_active)
    {
      if(Power.sleep_time == 0 && !Alarm.Alarm_active)
        sleep_mode(ENABLE); // sleep Counter counted to zero, and the display is still active, then turn it off and lower the voltage
      if(DataUpdate.Need_display_update == ENABLE)
      {
        DataUpdate.Need_display_update = DISPLAY;
        LcdClear_massive();
        if(screen == 1)
          main_screen();
        if(screen == 2)
          menu_screen();
        if(screen == 3)
          stat_screen();
      }
///////////////////////////////////////////////////////////////////////////////
    }
#ifdef version_401
    if (!Power.USB_active) && (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9)))
    {
      usb_activate(0x0); // If the USB power is beginning to be the included USB
    }
#endif

    if(!Power.USB_active) // if USB is not active, you can go to sleep
    {
      if(current_pulse_count < 30) // If the counter is not off scale, you can go to sleep
      {
        //if(DataUpdate.RTC_tick_update== = ENABLE) RTC_tick_processing();

        if(!Power.Pump_active && !Power.Sound_active)
        {
//#ifndef debug
          PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); // Go to sleep
//#endif
#ifdef debug
          Wakeup.total_wakeup++;
          DataUpdate.Need_display_update = ENABLE;
#endif

        } else
        {
          PWR_EnterSleepMode(PWR_Regulator_ON, PWR_SLEEPEntry_WFI);
#ifdef debug
          Wakeup.total_wakeup++;
          DataUpdate.Need_display_update = ENABLE;
#endif
        }
        //if(DataUpdate.RTC_tick_update== = ENABLE) RTC_tick_processing();
      }
    } else
      USB_work(); // if USB is active, try to transfer data
#ifdef debug
    Wakeup.total_cycle++;
    DataUpdate.Need_display_update = ENABLE;
#endif

  }
/////////////////////////////////////////////////////////////////////////////// 
}
come puoi notare non è così difficile capirci qualcosa...
una passata di traduzione, un file compare per vedere se tutto è OK e non sono stati introdotti strani errori... in meno di 30 minuti hai i sorgenti "ricommentati" in inglese!

P.S.: da cui la mia abitudine (escluso rari e specifici casi) di commentare sempre in inglese e non in italiano!


٩(•̮̮̃•̃)۶ - Excusatio non petita, accusatio manifesta

Rispondi

Torna a “Strumenti Autocostruiti”