Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'I2C'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - DIY
    • Projekty - DIY roboty
    • Projekty - DIY (mini)
    • Projekty - DIY (początkujący)
    • Projekty - DIY w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie

Kategorie

  • Quizy o elektronice
  • Quizy do kursu elektroniki I
  • Quizy do kursu elektroniki II
  • Quizy do kursów Arduino
  • Quizy do kursu STM32L4
  • Quizy do pozostałych kursów

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Imię


Strona

Znaleziono 15 wyników

  1. Cześć, od dłuższego czasu pracuję nad projektem o poniższych założeniach: - odczyt z 4 czujników IMU (24 osie) - szybkość akwizycji - 400-500 pomiarów na sekundę - mikrokontroler z serii F7 (wymogi późniejszej rozbudowy) - zapis na kartę SD lub bezprzewodowe przesłanie danych. Wpis ten jest tak naprawdę kontynuacją wątku STM32 UART wysyłanie danych typu uint16_t. Okazało się, że pomysł z bezprzewodowym przesyłaniem danych po UART jest trudny/nierealny do zrealizowania, więc postanowiłem wykorzystać zapis na kartę pamięci. Było z tym mnóstwo problemów (z zainteresowanymi chętnie się podzielę), ale koniec końców udało mi się zrealizować zapis w 4-bitowym trybie SDMMC. Obecnie zmagam się z problemem odpowiedniej szybkości pobierania danych z czterech MPU9250 podłączonych do dwóch linii I2C i ich zapisem na SD. Realizuję to w przerwaniu timera, które odpowiada za stałą szybkość akwizycji. Ustawiając zegary na maksymalne wartości pozwalające na skuteczny zapis na SD, podczas 1-minutowych testów z fs=400 Hz całkowity czas operacji wynosi ok. 65 sekund. Np. dla 100 Hz jest to dokładnie 60 sekund. Zatem program "nie wyrabia" owych 400 Hz. Wpadłem na pomysł, żeby czujniki podłączyć do 4 osobnych magistrali I2C i używać trybu IT, ale mój procesor ma tylko 1 pin (PC9) odpowiedzialny zarówno za I2C3_SDA, jak i MMC1_D1, czyli w moim przypadku nie da rady go użyć. Musiałbym wykorzystać wersję przynajmniej 176-pinową, a tych nie znalazłem dostępnych w Polsce. Póki co, aby nieco przyśpieszyć akwizycję, zastosowałem pewien (dziwny) trick i z każdej I2C jeden czujnik obsługuję trybem blokującym, a drugi z użyciem przerwania. Poniżej fragment kodu: uint8_t my_string[4*24+1]; //bez spacji void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM10) //przerwanie pochodzi od timera 10 { HAL_I2C_Mem_Read(&hi2c1, MPU9250_ACC_ADDRESS_A, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_A, 14, 50); //14 pomiarów od razu HAL_I2C_Mem_Read_IT(&hi2c1, MPU9250_ACC_ADDRESS_B, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_B, 14); //14 pomiarów od razu HAL_I2C_Mem_Read(&hi2c2, MPU9250_ACC_ADDRESS_C, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_C, 14, 50); //14 pomiarów od razu HAL_I2C_Mem_Read_IT(&hi2c2, MPU9250_ACC_ADDRESS_D, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_D, 14); //14 pomiarów od razu timer_tim10++; if (timer_tim10 <= 6*4000) { sprintf(my_string, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", MPU9250_Data_A[0],MPU9250_Data_A[1],MPU9250_Data_A[2],MPU9250_Data_A[3],MPU9250_Data_A[4],MPU9250_Data_A[5],MPU9250_Data_A[8],MPU9250_Data_A[9],MPU9250_Data_A[10],MPU9250_Data_A[11],MPU9250_Data_A[12],MPU9250_Data_A[13], MPU9250_Data_B[0],MPU9250_Data_B[1],MPU9250_Data_B[2],MPU9250_Data_B[3],MPU9250_Data_B[4],MPU9250_Data_B[5],MPU9250_Data_B[8],MPU9250_Data_B[9],MPU9250_Data_B[10],MPU9250_Data_B[11],MPU9250_Data_B[12],MPU9250_Data_B[13], MPU9250_Data_C[0],MPU9250_Data_C[1],MPU9250_Data_C[2],MPU9250_Data_C[3],MPU9250_Data_C[4],MPU9250_Data_C[5],MPU9250_Data_C[8],MPU9250_Data_C[9],MPU9250_Data_C[10],MPU9250_Data_C[11],MPU9250_Data_C[12],MPU9250_Data_C[13], MPU9250_Data_D[0],MPU9250_Data_D[1],MPU9250_Data_D[2],MPU9250_Data_D[3],MPU9250_Data_D[4],MPU9250_Data_D[5],MPU9250_Data_D[8],MPU9250_Data_D[9],MPU9250_Data_D[10],MPU9250_Data_D[11],MPU9250_Data_D[12],MPU9250_Data_D[13]); if(f_lseek(&fil, f_size(&fil)) != HAL_OK) printf("f_lseek ERROR\n"); if(f_write(&fil, my_string, sizeof(my_string), &numread) != HAL_OK) printf("f_write ERROR\n"); }else if (timer_tim10 == 6*4000+1) { close_file(); unmount_sd(); printf("done\n"); } } } Jak widać (mam nadzieję), czujnik A i B znajdują się na I2C1, C i D na I2C2. B i D odczytuję z użyciem przerwania (IT) po zakończeniu odczytu odpowiednio A i C. Jak mogę to zrobić szybciej? Domyślam się, że DMA mogłoby pomóc, ale kompletnie nie umiem tego zrobić. Zwykła zamiana _IT na _DMA nie działa. W sieci znalazłem mnóstwo wątków z problemami użycia DMA na F7, ale bez skutecznych (w moim przypadku) rozwiązań. Proszę tu o Waszą pomoc. A może mogę jakoś przyśpieszyć zapis na kartę pamięci? Czy tutaj można jakoś zaprząc do pacy DMA lub inny szybki mechanizm? Wydaje mi się też, że funkcja sprintf zajmuje sporo czasu. Usunąłem z niej wszystkie zbędne znaki i przesyłam jedynie po 2 na każdy rejestr oraz znak nowej linii po zapisaniu wszystkich potrzebnych rejestrów (w liczbie 48), czyli w sumie 97 znaków w każdej iteracji. Czy są jakieś szybsze alternatywy? Trochę się rozpisałem. Temat jest wielowątkowy, generuje różne problemy i zaskakujące niespodzianki. Starałem się zawrzeć tylko najważniejsze informacje. Testy przeprowadzam na Nucleo F746. Docelowo chciałem użyć 100-pinowego F756VGT6, ale może być inny (dostępny od ręki) z serii F7. STM32CubeIDE 1.10.1 MCU Package 1.17.0
  2. Witam wszystkich, bez zbędnych szczegółów mam do zrobienia układ który będzie musiał: Obsługa Xbee za pomocą magistrali UART Obsługa przetwornika A/C C/A (wstępnie myślałem nad układem pod magistralę I2C) Obsługa wyświetlacza OLED (również myślałem nad magistralą I2C ze względu na to że posiadam już takowy) Obsługa wyświetlacza LCD (chyba po magistrali SPI ok 3 cali) podgląd z kamery poprzez WiFi Obsługa WiFi jak w punkcie powyżej. Posiadać USB do kontrolera Ze względu na studencki budżet udało mi się kupić w bardzo dobrych pieniądzach (jak na obecną sytuację z "malinami") a są to Raspberry Pi zero wersje 1.3 oraz 1.1. Obawiam się, że jedna malinka nie podoła. Myślałem nad połączeniem dwóch za pomocą magistrali I2C ale wyczytałem, że Rasberry Pi może pracować tylko jako urządzenie typu Master i teraz nie wiem czy jedna dałaby rade podołać wszystkiemu czy dałoby radę jednak jakoś mądrze połączyć je i przesyłać proste informacje (może nawet kilka bitów) czy po prostu szukać czegoś mocniejszego aby obsługiwało wszystko. Miałby ktoś jakiś pomysł jak można by było ogarnąć temat z wykorzystaniem tego co mam, bądź co dałoby radę obsłużyć wszystkie potrzebne mi funkcje bez płacenia milionów monet? Zależy mi aby układ był stosunkowo niewielki i energooszczędny. Z góry dziękuję za wszystkie sugestie i pomysły oraz proszę o wyrozumiałość nie jestem aż tak biegły w temacie jak niektórzy doświadczeni użytkownicy i pasjonaci. Pozdrawiam!
  3. Dzień dobry mam problem z ekranem LCD z magistralą I2C który nie wyświetla znaków oprócz podreślika. Zworki na magistrali I2C nie nie było po zakupie więc przylutowałem kabelek. Może to być problem z kodem? Wykonywałem skanowanie I2C. #include <Wire.h> #include <LiquidCrystal.h> LiquidCrystal_I2C lcd(0x27); void setup() { lcd.begin(16,2); lcd.print("Hello, World! ") ; } void lopp() { }
  4. Witam Staram się podłączyć wyświetlacz na sterowniku SSD1306 do mikrokontrolera STM32F401RE. Posiadam dokładnie ten model wyświetlacza https://kamami.pl/wyswietlacze-oled-graficzne/560775-wyswietlacz-oled-waveshare-096-cala-a.html Chcę połączyć się z nim poprzez i2c i móc wyświetlać na nim tekst czy też figury. Mój kod wygląda aktualnie tak: /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "ssd1306.h" #include "test.h" #include "fonts.h" /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); /* USER CODE BEGIN PFP */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_I2C1_Init(); /* USER CODE BEGIN 2 */ SSD1306_Init(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ SSD1306_Clear(); SSD1306_GotoXY(5, 0); // coordinates x, y SSD1306_Puts("Hello", &Font_11x18, 1); // print Hello SSD1306_GotoXY(0, 24); // coordinates x, y SSD1306_Puts("ssd1306 OLED", &Font_7x10, 1); SSD1306_GotoXY(0, 40); // coordinates x, y SSD1306_Puts("display!", &Font_11x18, 1); SSD1306_UpdateScreen(); // update screen HAL_Delay(10000); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } Bazuje on głównie na poradnikach znalezionych w internecie. Nie jest zbyt skomplikowany, a jednak wyświetlacz w ogóle nie reaguje. Może ktoś ma pomysł co z tym zrobić lub doświadczenie w podobnym przypadku?
  5. Witam. Mam problemy z obsługą I2C na NodeMcu v3. NodeMCU v3 podłączony z LCM1602 tak jak na schemacie poniżej z tym że LCM1602 dostaje zasilanie 5V zasilacza, a GND z NodeMCU, LCM1602 i zasilacza są połączone razem. LCM1602 docelowo podłączony jest do wyświetlacza 20x4. 1. Po odpaleniu I2cScanner otrzymuję: Scanning... Unknown error at address 0x01 Unknown error at address 0x02 .... No I2C devices found 2. Po odpaleniu I2CexpDiag z https://github.com/duinoWitchery/hd44780 dostaję: Serial Initialized -------------------------------------------------------------------- I2CexpDiag - i2c LCD i/o expander backpack diagnostic tool -------------------------------------------------------------------- hd44780 lib version: 1.3.2 -------------------------------------------------------------------- Reported Arduino Revision: 1.8.16 Arduino Board: ESP8266_NODEMCU_ESP12E CPU ARCH: ESP8266 - F_CPU: 80000000 -------------------------------------------------------------------- SDA digital pin: 4 (GPIO4) SCL digital pin: 5 (GPIO5) -------------------------------------------------------------------- Checking for required external I2C pull-up on SDA - STUCK LOW Checking for required external I2C pull-up on SCL - STUCK LOW ******************************************************************** ERROR: SDA or SCL stuck pin ******************************************************************** I2C bus not usable Testowałem również na przypadkach gdzie na dwóch różnych expanderach LCM1602, gdzie nie ma podłączonego wyświetlacza i zasilacza, a zasilanie LCM1602 jest z pinu NodeMCU 3V, korzystałem również z różnych przewodów - efekt ten sam. Sprawdziłem też piny D1 i D2 - są zdrowe (jest prawidłowe napięcie gdy ustawiony jest stan wysoki, a po podłączeniu diody i odpaleniu testowego programu prawidłowo mruga). Ponadto sprawdziłem też to samo na innym ESP8266 - tym razem pod postacią Wemos D1 mini - tam sytuacja również jest taka sama. Czy pominąłem jakiś krok? Jakieś sugestie?
  6. Wpisując kod "HelloWorld" i po uruchomieniu ciągle wyświetla mi się to co na na przedstawionym zdjęciu
  7. Cześć, ponieważ I2C jest jednym z najprostszych szeregowych protokołów komunikacyjnych (i jest bardzo często stosowany) postanowiłem sprawdzić jak wygląda przykładowa implementacja na zestawie FPGA. Zacząłem od prostszej rzeczy, czyli implementacji "I2C slave" (poniekąd też slave jest mi bardziej przydatny do moich eksperymentów). Ponieważ projekt jest stosunkowo prosty i nie zajmuje dużo zasobów postanowiłem go przetestować na zestawie FPGA ElbertV.2 (ten używany w kursie FPGA Forbot'a). Masterem I2C będzie zwykłe "Arduino UNO" - z poziomu Arduino bardzo prosto można oprogramować komunikację po I2C z użyciem biblioteki Wire. Punktem wyjścia do implementacji "I2C Slave" jest darmowy projekt zamieszczony na stronie opencores.org. Tutaj link do projektu: https://opencores.org/projects/i2cslave Projekt ma stosunkowo prostą budowę i jest właściwie tylko szkieletem do budowy na jego podstawie bardziej skomplikowanych układów (będzie to wyjaśnione dalej). Jak przeważnie się to zdarza trzeba było dodać nowy zegar (DCMs 1 ze Spartan3A) 48 MHz (pętla PLL), ponieważ oryginalny projekt pracował z takim zegarem. Po wykonaniu potrzebnych przeróbek projekt zajmuje niecałe 30% zasobów układu Spartan3 z Elberta - patrz screen: Jak można zobaczyć na podglądzie RTL - top entity projektu ma bardzo prosty interfejs - patrz screen: Tutaj kod w Verilog'u głównego modułu projektu (już po dodaniu zegara PLL 48 MHz) `include "i2cSlave_define.v" module i2cSlaveTop ( clk, rst, sda, scl, myReg0 ); input clk; input rst; inout sda; input scl; output [7:0] myReg0; wire clk48Mhz, clkBufg; // Instantiate the module PLL clock PLL_clock PLL_48Mhz ( .CLKIN_IN(clk), .RST_IN(~rst), .CLKFX_OUT(clk48Mhz), .CLKIN_IBUFG_OUT(clkBufg) ); i2cSlave u_i2cSlave( .clk(clk48Mhz), .rst(~rst), .sda(sda), .scl(scl), .myReg0(myReg0), .myReg1(), .myReg2(), .myReg3(), .myReg4(8'h12), .myReg5(8'h34), .myReg6(8'h56), .myReg7(8'h78) ); endmodule Jak widać "i2cSlaveTop" ma trzy wejścia: clk - główny zegar projektu (w Elbercie 12 Mhz) rst - reset asynchroniczny - stanem High więc dla naszej płytki FPGA trzeba go było zanegować scl - zegar magistrali I2c , jedno wejście/wyjście (inout) sda - dane magistrali I2C i jedno wyjście (wektor 8 bitów) myReg0 - na tym wyjściu równoległym będą się pojawiać dane wysłane przez mastera I2C (Arduino UNO), dlatego podłączymy je do diod LED w zestawie Elbert, aby móc te dane łatwo obserwować. Tutaj treść pliku ucf (user constraints) dla płytki FPGA Elbert: NET "clk" LOC = P129 | IOSTANDARD = LVCMOS33 | PERIOD = 12MHz; NET "rst" PULLUP; NET "rst" LOC = P76; NET "sda" LOC = P31 | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 12; NET "scl" LOC = P32 | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 12; # myReg0 - 8 bit data NET "myReg0[7]" LOC = P46 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "myReg0[6]" LOC = P47 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "myReg0[5]" LOC = P48 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "myReg0[4]" LOC = P49 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "myReg0[3]" LOC = P50 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "myReg0[2]" LOC = P51 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "myReg0[1]" LOC = P54 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "myReg0[0]" LOC = P55 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; Jak widać zdefiniowany jest domyślny pin zegara (12 MHz), reset - dolny z pięciu switchy, diody LED (myReg0 - dane przesłane po I2C do płytki Elbert), scl i sda 2 piny magistarli I2C (pierwsze dwa piny złącza P1 na płytce Elbert - patrz rysunek: Jeśli chodzi o piny magistrali I2C (scl, sda) od strony Arduino UNO to zaznaczyłem je fioletową obwódką na rysunku pinout'u dla UNO: Oczywiście pomiędzy zestawem FPGA (poziom logiki 3,3V) a Arduini UNO (poziom logiki 5V) trzeba wstawić na tych dwóch liniach (scl, sda) konwertery poziomów logicznych.Ja zrobiłem to za pomocą takiego konwertera poziomów (bo tylko taki miałem pod ręką) https://botland.com.pl/pl/konwertery-napiec/2523-konwerter-poziomow-logicznych-dwukierunkowy-4-kanalowy-pololu.html Tutaj zdjęcie całego układu (konwerter poziomów na płytce stykowej): Skoro połączenia mamy omówione wróćmy może do kodu projektu (Verilog). Przejdżmy do pliku "i2cSlave_define.v" plik ten jest dołączany (dyrektywa include) za pomocą linii: `include "i2cSlave_define.v" do wszystkich plików żródłowych projektu (Verilog) podobnie jak w języku C. W pliku tym mamy zdefiniowane bardzo ważne parametry modulów - patrz źródła: // ----------------------- i2cSlave_define.v -------------------- // stream states `define STREAM_IDLE 2'b00 `define STREAM_READ 2'b01 `define STREAM_WRITE_ADDR 2'b10 `define STREAM_WRITE_DATA 2'b11 // start stop detection states `define NULL_DET 2'b00 `define START_DET 2'b01 `define STOP_DET 2'b10 // i2c ack and nak `define I2C_NAK 1'b1 `define I2C_ACK 1'b0 // ---------------------------------------------------------------- // ------------- modify constants below this line ----------------- // ---------------------------------------------------------------- // i2c device address `define I2C_ADDRESS 7'h3c // System clock frequency in MHz // If you are using a clock frequency below 24MHz, then the macro // for SDA_DEL_LEN will result in compile errors for i2cSlave.v // you will need to hand tweak the SDA_DEL_LEN constant definition `define CLK_FREQ 48 // Debounce SCL and SDA over this many clock ticks // The rise time of SCL and SDA can be up to 1000nS (in standard mode) // so it is essential to debounce the inputs. // The spec requires 0.05V of hysteresis, but in practise // simply debouncing the inputs is sufficient // I2C spec requires suppresion of spikes of // maximum duration 50nS, so this debounce time should be greater than 50nS // Also increases data hold time and decreases data setup time // during an I2C read operation // 10 ticks = 208nS @ 48MHz `define DEB_I2C_LEN (10*`CLK_FREQ)/48 // Delay SCL for use as internal sampling clock // Using delayed version of SCL to ensure that // SDA is stable when it is sampled. // Not entirely citical, as according to I2C spec // SDA should have a minimum of 100nS of set up time // with respect to SCL rising edge. But with the very slow edge // speeds used in I2C it is better to err on the side of caution. // This delay also has the effect of adding extra hold time to the data // with respect to SCL falling edge. I2C spec requires 0nS of data hold time. // 10 ticks = 208nS @ 48MHz `define SCL_DEL_LEN (10*`CLK_FREQ)/48 // Delay SDA for use in start/stop detection // Use delayed SDA during start/stop detection to avoid // incorrect detection at SCL falling edge. // From I2C spec start/stop setup is 600nS with respect to SCL rising edge // and start/stop hold is 600nS wrt SCL falling edge. // So it is relatively easy to discriminate start/stop, // but data setup time is a minimum of 100nS with respect to SCL rising edge // and 0nS hold wrt to SCL falling edge. // So the tricky part is providing robust start/stop detection // in the presence of regular data transitions. // This delay time should be less than 100nS // 4 ticks = 83nS @ 48MHz `define SDA_DEL_LEN (4*`CLK_FREQ)/48 Dla nas najważniejsze są dwa parametry: `define I2C_ADDRESS 7'h3c Pierwszy to adres naszego slave'a w magistrali I2C (jest dostepnych 128 różnych adresów) - wynosi on 3C zapisany heksadecymalnie. Drugi to częstotliwość zegara - 48 MHz: `define CLK_FREQ 48 Teraz drugi plik "registerInterface": `include "i2cSlave_define.v" module registerInterface ( clk, addr, dataIn, writeEn, dataOut, myReg0, myReg1, myReg2, myReg3, myReg4, myReg5, myReg6, myReg7 ); input clk; input [7:0] addr; input [7:0] dataIn; input writeEn; output [7:0] dataOut; output [7:0] myReg0; output [7:0] myReg1; output [7:0] myReg2; output [7:0] myReg3; input [7:0] myReg4; input [7:0] myReg5; input [7:0] myReg6; input [7:0] myReg7; reg [7:0] dataOut; reg [7:0] myReg0; reg [7:0] myReg1; reg [7:0] myReg2; reg [7:0] myReg3; // --- I2C Read always @(posedge clk) begin case (addr) 8'h00: dataOut <= myReg0; 8'h01: dataOut <= myReg1; 8'h02: dataOut <= myReg2; 8'h03: dataOut <= myReg3; 8'h04: dataOut <= myReg4; 8'h05: dataOut <= myReg5; 8'h06: dataOut <= myReg6; 8'h07: dataOut <= myReg7; default: dataOut <= 8'h00; endcase end // --- I2C Write always @(posedge clk) begin if (writeEn == 1'b1) begin case (addr) 8'h00: myReg0 <= dataIn; 8'h01: myReg1 <= dataIn; 8'h02: myReg2 <= dataIn; 8'h03: myReg3 <= dataIn; endcase end end endmodule Plik ten jest o tyle ważny, że widać w nim iż w projekcie jest używanych 8 rejestrów 8-mio bitowych (cztery wejściwe i cztery wyjściowe). Ale tylko jeden rejestr jest w głównym module (implementacja jest trochę niepełna - o czym autor pisze, że jest to punkt wyjścia do własnych implementacji). Dla nas jest jedynie istotne, że dla adresu 8'h00 (czyli 0 dziesiętnie rejestr myReg0 jest obsługiwany poprawnie), będzie to istotne przy pisaniu mastera I2C na Arduino UNO. Tutaj zamieszczam działający projekt " I2C slave" (dla Elbert'a) - Xilinx ISE 14.7: I2CSlave01.zip Jeśli ktoś nie chce uruchamiać syntezy może od razu załadować za pomocą programu "Elbert V2 Configurator" plik "i2cslavetop.bin" do zestawu FPGA. Po wgraniu do zestawu FPGA Elbert pliku konfiguracji i wykonaniu połączeń z Arduino UNO możemy przejść do programu dla Arduino. Najpierw warto programem "I2C scanner" sprawdzić, czy Arduino z załadowanym programem skanera wykryje nam slave'a i2C pod adresem 0x3C. Tutaj kod progrmu "I2C scanner" - program należy skompilować za pomocą "Arduino IDE" i wgrać do płytki Arduino UNO. Kod programu: #include <Wire.h> void setup() { Wire.begin(); Serial.begin(9600); while (!Serial); // Leonardo: wait for serial monitor Serial.println("\nI2C Scanner"); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); // wait 5 seconds for next scan } Tak wygląda prawidłowe wykrycie slave'a (FPGA) pod adresem 0x3C na magistrali I2C przez Arduino: Jeśli to zadziała, to możemy wgrać taki krótki program mastera I2C na Arduino UNO: #include <Wire.h> void setup() { Wire.begin(); // join i2c bus (address optional for master) } byte x = 0; void loop() { Wire.beginTransmission(0x3C); // transmit to device #3C Wire.write(0); //wysylamy adres rejestru 0 (ten odczytany w kodzie Verilog) Wire.write(x); // wysylamy jeden bajt - wartosc x Wire.endTransmission(); // stop transmitting x++; delay(500); } Jeśli wszystko poszło OK, możemy obserwować na diodach zestawu Elbert zmienijącą się wartość x (inkrementowaną co jeden obieg pętli głównej programu) przesyłaną z mastera (Arduino) do slave'a (FPGA). Patrz filmik (sorry nie mogę przesłać na forbot pliku mp4 z filmem). Pozdrawiam
  8. Cześć, potrzebuję ekspandera na minimum 2 piny na magistralę i2c. Nie byłby to problem tylko że muszę mieć sygnał PWM o częstotliwości najlepiej 25kHz. Ale może być coś w zakresie 21-28kHz. Zna ktoś taki układ który by się do tego nadawał?
  9. Cześć, szukałem dziś w internecie odpowiedzi jaka może być maksymalna długość magistrali I2C dla której pracuje ona bez błędów transmisji z zegarem 100 KHz. Spotkałem się też z opisami kilku sposobów "wydłużania" magistrali - poczynając od doboru rezystorów pull-up, poprzez klucze na tranzystorach MOSFET, czy specjalizowane układy scalone. Odpowiedzi są jednak z bardzo dużym rozrzutem, niektórzy podają odległości rzędu 200 czy 80 m, podczas gdy inni mówią o odległościach rzędu 4-6 metrów. Czy ktoś z forumowiczów robił może swoje doświadczenia w tym zakresie i może się podzielić ich wynikami. Planuję zrobić własne eksperymenty, ale nie jestem pewien która metoda gwarantuje najlepsze osiągi - może ktoś może coś podpowiedzieć. Zadowoliła by mnie praca magistrali bez błędów na odległóść rzędu 4 do 6 metrów (przy zegarze 100 KHz). Pozdrawiam
  10. //TEN DZIAŁA POPRAWNIE #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <SoftwareSerial.h> int wartoscAnalog=0; byte wartoscZmapowana=0; char info[96]; LiquidCrystal_I2C lcd(0x27,16,2); void setup() { lcd.init(); lcd.backlight(); lcd.setCursor(0,0); } void loop() { lcd.clear(); lcd.setCursor(0,0); lcd.print(wartoscZmapowana); wartoscAnalog=analogRead(A0); wartoscZmapowana=map(wartoscAnalog, 0, 1023, 0, 100); delay(1000); } // TEN ZLE WYSWIETLA #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <SoftwareSerial.h> #include "DHT.h" #define DHTTYPE DHT22 #define DHTPIN 6 #define WIATRAK 7 int wartoscAnalog=0; byte wartoscZmapowana=1; char info[96]; int buzzer=11; LiquidCrystal_I2C lcd(0x27,16,2); DHT dht(DHTPIN, DHTTYPE); void setup() { dht.begin(); //START DHT lcd.init(); lcd.backlight(); lcd.setCursor(0,0); pinMode(WIATRAK,OUTPUT); } void loop() { float h = dht.readHumidity(); float t = dht.readTemperature(); float f = dht.readTemperature(true); if (isnan(h) || isnan(t) || isnan(f)) { lcd.print(F("Failed to read from DHT sensor!")); return; } float hif = dht.computeHeatIndex(f, h); float hic = dht.computeHeatIndex(t, h, false); lcd.clear(); lcd.setCursor(0,0); lcd.print(wartoscZmapowana); wartoscAnalog=analogRead(A0); wartoscZmapowana=map(wartoscAnalog, 0, 1023, 0, 100); if(t>35) { wyswietlanie(); BuzzerWiatrak(); } if(wartoscZmapowana==0) { lcd.clear(); lcd.setCursor(4,0); lcd.print("alarm"); } if(wartoscZmapowana>20) { wyswietlanie(); BuzzerWiatrak(); } else { digitalWrite(WIATRAK, LOW); } //delay(1000); } void wyswietlanie() { lcd.clear(); lcd.setCursor(4,0); lcd.print("Pozar"); } void BuzzerWiatrak() { digitalWrite(WIATRAK, HIGH); tone(buzzer,450); delay(500); noTone(buzzer); delay(500); } Witam, mam problem, mianowicie mam projekcik(lcd, czujka dymu, czujka temperatury, buzzer i wiatrak). Arduino nie wyświetla poprawnie teksu( nie wyswietla wszystkiego).W momencie wykonania warunku (if) gdy np temperatura jest za wysoka wszystko działa(wyświetla prawidłowo) Natomiast gdy wgram prosty program(tylko czujka dymu i lcd) wszystko wyświetla prawidłowo. Dodam że wyświetlacz to LCD 1602 pod magistrale I2C a arduino uno klon. Macie jakieś pomysły jak to naprawic? W załączniku prześle jedno zdjecie z niewłaściwym wyświetleniem, a drugie z poprawnym(przy maly programie). Dzieki i pozdrawiam
  11. Dzień dobry Mam połączone Arduino Mega z Uno przy pomocy I2C do komunikacji. Mega jest "master", który po wciśnięciu przycisku wysyła wartość zmiennej "stan". Uno jako "slave" ma tą wartość odczytać i wykonać odpowiednie polecenie. I tu jest problem, ponieważ o ile Mega wysyła wartość (gdy sprawdzam status transmisji komendą: unsigned char statuss = Wire.endTransmission(); Serial.println (statuss); to wartość "statuss" = 0, czyli sukces) to gdy sprawdzam monitor Uno, to nic tam nie ma do wyświetlenia. Czy mógłby mi ktoś powiedzieć gdzie występuje błąd w mojej pracy ? Kod dla Mega: // Enable debug prints to serial monitor #define MY_DEBUG // Enable serial gateway #define MY_GATEWAY_SERIAL // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender) #if F_CPU == 8000000L #define MY_BAUD_RATE 38400 #endif // Enable inclusion mode #define MY_INCLUSION_MODE_FEATURE // Enable Inclusion mode button on gateway #define MY_INCLUSION_BUTTON_FEATURE // Inverses behavior of inclusion button (if using external pullup) //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP // Set inclusion mode duration (in seconds) #define MY_INCLUSION_MODE_DURATION 60 // Digital pin used for inclusion mode button #define MY_INCLUSION_MODE_BUTTON_PIN 3 #define MY_REPEATER_FEATURE //----------------biblioteki----------------------------- #include <SPI.h> #include <MFRC522.h> //RFID RC522 #include <Wire.h> //Dla I2C #include <Bounce2.h> //Obsługa przycisków #include <MySensors.h> //------------------------------------------------------- //----------------definiowanie elementów----------------- #define BUTTON_PIN 31 #define RELAY_1 24 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define NUMBER_OF_RELAYS 1 // Total number of attached relays #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay //------------------------------------------------------- //----------------zmienne-------------------------------- Bounce debouncer = Bounce(); volatile boolean stan = true; //------------------------------------------------------- //------------------------------------------------------- void before() { for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) { // Then set relay pins in output mode pinMode(pin, OUTPUT); // Set relay to last known state (using eeprom storage) digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); } } //------------------------------------------------------- //------------------------------------------------------- void setup() { // Setup locally attached sensors delay(5000); // Setup the button. pinMode(BUTTON_PIN, INPUT_PULLUP); // After setting up the button, setup debouncer. debouncer.attach(BUTTON_PIN); debouncer.interval(5); digitalWrite(RELAY_1, LOW); //Inne Serial.begin(9600); SPI.begin(); } //------------------------------------------------------- //------------------------------------------------------- // Główna funkcja sterująca void loop() { // Send locally attached sensor data here if (debouncer.update()) { // Get the update value. int value = debouncer.read(); // Send in the new value. if(value == LOW) { stan = !stan; Serial.println(stan); Wire.beginTransmission(1); Wire.write(stan); // sends one byte Wire.endTransmission(); unsigned char statuss = Wire.endTransmission(); Serial.println (statuss); } } } //------------------------------------------------------- Kod dla Uno: //----------------biblioteki----------------------------- #include <Servo.h> //Servo #include <Wire.h> //Dla I2C //------------------------------------------------------- //----------------zmienne-------------------------------- volatile byte stan = 1; //------------------------------------------------------- //------------------------------------------------------- void setup() { Serial.begin(9600); Wire.begin(1); } //------------------------------------------------------- //------------------------------------------------------- // Główna funkcja sterująca void loop() { Wire.onReceive(czytaj); } //------------------------------------------------------- //------------------------------------------------------- void czytaj(int howMany) { if (Wire.available()) { stan = Wire.read(); // receive byte as a character Serial.println(stan); } } //------------------------------------------------------- Jeśli chodzi o połączenia to na pewno są dobrze, ponieważ gdy wczytam przykłady z biblioteki "Wire" to komunikacja działa poprawnie. Może źle korzystam z biblioteki "MySensors" ?
  12. Cześć, bawię się od dłuższego czasu "arducam". Mam surowy moduł OV7670 bez ramu i walcze z nim na arduino nano. Już wcześniej udało mi się za pomocą samej atmegi 328 wyciągnąć z tej kamerki obraz, ale wtedy powiedzmy że nie wnikałem w ustawianie rejestrów kamerki, ściągnałem gotowca, dopasowałem do swojego uC, wgrałem i jakoś to działało. Teraz chciałem podejść do tematu troche ambitniej i ogarnąć sobie ustawienia kamerki( zmiana rozdzielczości, naświetlenia itd), no i zacząłem bawić się interfejsem SCCB kamerki. No i pojawiły się kłopoty. Do komunikacji od strony arduino użyłem biblioteki Wire i skopiowałem kawałek kodu z githuba ArduCAM do odczytywania pojedynczego rejestru. No nie działało mi to, więc podpiąłem analizator stanów logicznych, i sie okazało że jedno z drugim za bardzo rozmawiać nie chce. Ogólnie sygnały wyglądaja dziwnie, w pewnych momentach zegar i2c ma częstotliwość 8mhz. Kamerka wystawia sygnały na szynie danych i VSYNC, HS czy PCLK, ale przy zakrywaniu obiektywu to co pojawia się na D[0:7] nie różni się niczym od tego co jest przy odkrytym obiektywie, i przez to zastanawiam się czy ta kamerka nie jest uszkodzona (mimo że sygnały z niej jakieś wychodzą). Przyznam się, że zapomniałem się że kamerka operuje na 3,3V i podałem zegar bezpośrednio z pinu arduino na pin OV7670 Podrzucam szkic i zrzut z analizatora dla odczytu rejestru 0x12. Ma ktoś jakieś doświadczenia w tym temacie? Co o tym myślicie? Pzdr i2c_test.rar
  13. Mam wyświetlacz 1602A i moduł i2c (PCF8574AT), jak podłączam do arduino GND - GND Vcc - 5V SDA- A4 SCL - A5 to skaner i2c nie pokazuje adresu. Jednak czytając datasheety adres to 0x3F i jak wgrywam do przykładów podstawowy program, to wyświetlacz nic nie pokazuje. Kontrast działa, a korzystam z biblioteki NewLiquidCrystal (najnowszej wersji).
  14. Dzień Dobry wszystkim, założyłem ten temat ponieważ nigdzie nie moge znaleść odpowiedzi na swoje pytanie a mianowicie, dlaczego nie otrzymuje adresu konwertera i2c ? Po załączonych zdjęciach widac ze magistrala i2c nie kończy transmisji , ktoś byłby to w stanie wytłumaczyc ?
  15. Kryptowaluty zdobyły już dość dużą popularność, dlatego pomyślałem, że ciekawym projektem byłoby zrobienie z pomocą maliny wyświetlacza aktualnego kursu kryptowalut. W paru krokach postaram się przedstawić jak wykonać taki projekt. Do budowy wykorzystałem: Raspberry pi 3B+ Wyświetlacz LCD 4x20 znaków niebieski + konwerter I2C Konwerter poziomów logicznych dwukierunkowy Płytka stykowa Przewody żeńsko-męskie Etapy wykonania projektu: 1. Podłączenie wyświetlacza 2. Uruchomienie I2C Użyłem Raspbiana Jessie Lite jako systemu do naszej maliny, pierwszym krokiem będzie uruchomienie I2C: - wpisujemy w konsolę sudo raspi-config - następnie wybieramy opcję numer 5 - później przechodzimy do zakładki I2C - i wybieramy yes - wychodzimy z configu maliny i wykonujemy restart wpisując: sudo reboot - jeśli wszystko wykonaliśmy poprawnie powinniśmy ujrzeć to po wpisaniu komendy (przedstawiony adres może się różnić od waszego) i2cdetect -y 1 3. Pobranie biblioteki do obsługi ekranu - po uruchomieniu I2C w Raspberry należy pobrać bibliotekę komendą: git clone https://gist.github.com/6ad9020b3c84bc65b53119b21a4bc37d.git i2c_lcd - po pobraniu wchodzimy do folderu z tą biblioteką: cd i2c_lcd - teraz należy ustawić adres I2C w pliku i2c_lcd.py: sudo nano i2c_lcd.py - w tym miejscu wpisujemy adres, który ujrzeliśmy wcześniej przy używaniu komendy i2cdetect: - nie wychodząc z edytora zmieniamy wyświetlaną szerokość na 20: - wychodzimy i zapisujemy plik naciskając kolejno CTRL+X Y Enter - uruchamiamy test naszego wyświetlacza: python i2c_lcd.py - jeśli wykonaliśmy wszystko poprawie to powinniśmy ujrzeć coś takiego: 4. Program do odczytu i wyświetlania kryptowalut - tworzymy plik crypto.py komendą: sudo nano crypto.py - i wklejamy kod: import i2c_lcd import requests import time space = 6 i2c_lcd.lcd_init() i2c_lcd.lcd_string("-Kursy kryptowalut-",i2c_lcd.LCD_LINE_1) i2c_lcd.lcd_string("---Aktualny kurs---",i2c_lcd.LCD_LINE_2) r = 0 while True: #btc print('btc') r = requests.get('https://api.cryptonator.com/api/ticker/btc-usd') crypto = r.json()['ticker']['price'] crypto = float(crypto) crypto = round(crypto, 2) crypto = str(crypto) i2c_lcd.lcd_string("------Bitcoina------",i2c_lcd.LCD_LINE_3) i2c_lcd.lcd_string(" $"+crypto,i2c_lcd.LCD_LINE_4) time.sleep(space) #eth print('eth') r = requests.get('https://api.cryptonator.com/api/ticker/eth-usd') crypto = r.json()['ticker']['price'] crypto = float(crypto) crypto = round(crypto, 2) crypto = str(crypto) i2c_lcd.lcd_string(" $"+crypto,i2c_lcd.LCD_LINE_4) i2c_lcd.lcd_string("------Ethereum------",i2c_lcd.LCD_LINE_3) time.sleep(space) #bch print('bch') r = requests.get('https://api.cryptonator.com/api/ticker/bch-usd') crypto = r.json()['ticker']['price'] crypto = float(crypto) crypto = round(crypto, 2) crypto = str(crypto) i2c_lcd.lcd_string(" $"+crypto,i2c_lcd.LCD_LINE_4) i2c_lcd.lcd_string("----BitcoinCasha----",i2c_lcd.LCD_LINE_3) time.sleep(space) #ltc print('ltc') r = requests.get('https://api.cryptonator.com/api/ticker/ltc-usd') crypto = r.json()['ticker']['price'] crypto = float(crypto) crypto = round(crypto, 2) crypto = str(crypto) i2c_lcd.lcd_string("------Litecoina------",i2c_lcd.LCD_LINE_3) i2c_lcd.lcd_string(" $"+crypto,i2c_lcd.LCD_LINE_4) time.sleep(space) #doge print("doge") r = requests.get('https://api.cryptonator.com/api/ticker/doge-usd') crypto = r.json()['ticker']['price'] crypto = float(crypto) crypto = round(crypto, 6) crypto = str(crypto) i2c_lcd.lcd_string(" $"+crypto,i2c_lcd.LCD_LINE_4) i2c_lcd.lcd_string("------Dogecoina-----",i2c_lcd.LCD_LINE_3) time.sleep(space) - po zapisaniu uruchamiamy program: sudo python crypto.py - jeśli wszystko wykonaliśmy poprawnie powinniśmy ujrzeć coś takiego: Gotowe możemy monitorować kurs kryptowalut 🙂
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.