W kolejnym poście dodam kod pod Arduino UNO i coś tam napiszę o konstrukcji. Wersja na razie testowa. Do zmiany pójdą silniki (za słabe sobie nie radzą).
wtorek, 21 lutego 2017
czwartek, 3 listopada 2016
piątek, 1 kwietnia 2016
sobota, 26 marca 2016
środa, 10 czerwca 2015
Autodesk Inventor 2012 - przekładnia walcowa
Witam!
Dzisiaj troszkę z innej beczki niż programowanie, ale generalnie temat
powinni znać konstruktorzy/programiści zajmujący się projektowaniem
części do swoich robotów, a później np. ich drukowaniem tak jak
ja sobie własnie z tym radzę :).
Myślę, że w przyszłości na blogu pojawi się kurs video obsługi,
projektowania części mechanicznych np: do robotów przy użyciu
Autodesk Inventora.
Dzisiaj chciałbym pokazać mały drobiazg jakim jest dokładne odwzorowanie
przekładni zębatej walcowej, która została narysowana w wyżej wymienionym
programie.
Kilka screenów:
Dzisiaj troszkę z innej beczki niż programowanie, ale generalnie temat
powinni znać konstruktorzy/programiści zajmujący się projektowaniem
części do swoich robotów, a później np. ich drukowaniem tak jak
ja sobie własnie z tym radzę :).
Myślę, że w przyszłości na blogu pojawi się kurs video obsługi,
projektowania części mechanicznych np: do robotów przy użyciu
Autodesk Inventora.
Dzisiaj chciałbym pokazać mały drobiazg jakim jest dokładne odwzorowanie
przekładni zębatej walcowej, która została narysowana w wyżej wymienionym
programie.
Kilka screenów:
A tak wygląda obiekt namacalny:
Pozdrawiam
wtorek, 13 stycznia 2015
C# - Parsowanie pliku CSV
Witajcie.
Czasem, może zajść potrzeba odczytania zawartości pliku csv (comma separated values)
czyli jest to plik, który ma zawartość rozdzieloną przecinkami bądź średnikami.
Taki plik jeśli otworzymy jakimkolwiek edytorem tekstu zobaczymy właśnie
dane rozdzielone wspomnianymi znakami.
Przykład:
ID;Imie;Nazwisko;NazwaFirmy;Adres
1;Janek;Kowalski;
ACME;USA;
2;Malgosia;Kowalska;
ACME2;Polska;
3;Kubus;Puchatek;
Lasek;GB;
4;Papa;Serf;
Smerfolandia;Smerfolas;
5;Gargus;Gargamel;
Dom;KoloLasuSmerfow;
W klasie dodajemy pięć właściwości zgodnie z tym jaki mamy nagłówek w pliku csv
Klasa ParseFile:
ścieżkę do pliku csv. Dalej widzimy konstruktor klasy, który jako parametr
przyjmuje ścieżkę do pliku a string ten jest zapisywany do pola z którego skorzysta
dalej metoda odczytująca i parsująca dane.
Następnie widzimy publiczną metodę OdczytajPlik(). Metoda zwraca listę typu Employee.
Dalej tworzymy nową listę "listaWyjściowa" typu Employee do której zapiszemy nasze
dane wyjściowe. w kolejnej linii odczytujemy zawartość całego pliku, przy czym
pomijamy pierwszy wiersz, który nie jest nam do niczego już potrzebny.
Teraz uwaga. Aby było trudniej to plik tak spreparowałem aby dane były rozbite na
dwa wiersze. I teraz w pętli for jedziemy pętlą co drugi wiersz i sklejamy stringi ze sobą.
Myślę, że to w kodzie ładnie widać. Teraz nasze dane mają postać listy tablicy stringów
List<string[]>, czyli należy teraz po kolekcji przejechać się np: pętlą foreach
po kolekcji daneZPliku i wyłuskamy po kolei każdy string rozbity średnikiem.
Po działaniu metody Split() dostaniemy tablicę stringów - czyli w sumie wyjdzie ich
w każdym wierszu po 5 sztuk :). Teraz do listy wyjściowej dodajemy indeksy.
Na końcu zwracamy listę.
Teraz w głównej formie dodajemy kontrolkę DataGridView i np: możemy dodać
button.
do pliku csv. Dalej nasz obiekt będzie posiadał metodę OdczytajPlik(), którą
dopiero co stworzyliśmy. Kontrolka DataGridView posiada własciwość DataSource
gdzie podamy nasze źródło danych.
Rezultat w gridzie.
Czasem, może zajść potrzeba odczytania zawartości pliku csv (comma separated values)
czyli jest to plik, który ma zawartość rozdzieloną przecinkami bądź średnikami.
Taki plik jeśli otworzymy jakimkolwiek edytorem tekstu zobaczymy właśnie
dane rozdzielone wspomnianymi znakami.
Przykład:
ID;Imie;Nazwisko;NazwaFirmy;Adres
1;Janek;Kowalski;
ACME;USA;
2;Malgosia;Kowalska;
ACME2;Polska;
3;Kubus;Puchatek;
Lasek;GB;
4;Papa;Serf;
Smerfolandia;Smerfolas;
5;Gargus;Gargamel;
Dom;KoloLasuSmerfow;
Jest to zawartość, pliku jaki sobie przygotowałem a który odczytamy. Jak widać
plik zawiera nagłówek, czyli dla nas będą to nazwy kolumn.
Ok. Stwórzmy projekt winformsowy, ponieważ dla lepszego zobrazowania
dane wrzucimy do kontrolki DataGridView.
Do projektu dodamy dwie klasy. Pierwszą nazwijmy "Employee" a drugą
"ParseFile"
Klasa Employee:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ParseCSVfile
{
public class Employee
{
public string ID { get; set; }
public string Imie { get; set; }
public string Nazwisko { get; set; }
public string NazwaFirmy { get; set; }
public string Adres { get; set; }
}
}
W klasie dodajemy pięć właściwości zgodnie z tym jaki mamy nagłówek w pliku csv
Klasa ParseFile:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ParseCSVfile
{
public class ParseFile
{
private string sciezka;
public ParseFile(string sciezka)
{
this.sciezka = sciezka;
}
public List OdczytajPlik()
{
try
{
List listaWyjsciowa = new List();
string[] dane = File.ReadAllLines(sciezka).Skip(1).ToArray();
List daneZPliku = new List();
for (int i = 0; i < dane.Length; i += 2)
{
daneZPliku.Add(String.Format("{0}{1}", dane[i], dane[i + 1]));
}
foreach (string wiersz in daneZPliku)
{
string[] wierszRozbity = wiersz.Split(';');
listaWyjsciowa.Add(new Employee
{
ID = wierszRozbity[0],
Imie = wierszRozbity[1],
Nazwisko = wierszRozbity[2],
NazwaFirmy = wierszRozbity[3],
Adres = wierszRozbity[4],
});
}
return listaWyjsciowa;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
}
Zacznijmy od góry. Stworzyliśmy prywatne pole w którym będziemy przetrzymywaliścieżkę do pliku csv. Dalej widzimy konstruktor klasy, który jako parametr
przyjmuje ścieżkę do pliku a string ten jest zapisywany do pola z którego skorzysta
dalej metoda odczytująca i parsująca dane.
Następnie widzimy publiczną metodę OdczytajPlik(). Metoda zwraca listę typu Employee.
Dalej tworzymy nową listę "listaWyjściowa" typu Employee do której zapiszemy nasze
dane wyjściowe. w kolejnej linii odczytujemy zawartość całego pliku, przy czym
pomijamy pierwszy wiersz, który nie jest nam do niczego już potrzebny.
Teraz uwaga. Aby było trudniej to plik tak spreparowałem aby dane były rozbite na
dwa wiersze. I teraz w pętli for jedziemy pętlą co drugi wiersz i sklejamy stringi ze sobą.
Myślę, że to w kodzie ładnie widać. Teraz nasze dane mają postać listy tablicy stringów
List<string[]>, czyli należy teraz po kolekcji przejechać się np: pętlą foreach
po kolekcji daneZPliku i wyłuskamy po kolei każdy string rozbity średnikiem.
Po działaniu metody Split() dostaniemy tablicę stringów - czyli w sumie wyjdzie ich
w każdym wierszu po 5 sztuk :). Teraz do listy wyjściowej dodajemy indeksy.
Na końcu zwracamy listę.
Teraz w głównej formie dodajemy kontrolkę DataGridView i np: możemy dodać
button.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ParseCSVfile
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ParseFile dane = new ParseFile(@"c:\Users\Documents\1.csv");
dataGridView1.DataSource = dane.OdczytajPlik();
}
}
}
W zdarzeniu buttona tworzymy nowy obiekt typu ParseFile i podajemy ścieżkędo pliku csv. Dalej nasz obiekt będzie posiadał metodę OdczytajPlik(), którą
dopiero co stworzyliśmy. Kontrolka DataGridView posiada własciwość DataSource
gdzie podamy nasze źródło danych.
Rezultat w gridzie.
I to by było na koniec. Powodzenia w parsowaniu plików csv.
czwartek, 8 stycznia 2015
C# - odczyt pliku XML do DataGridView
Witajcie!
Chciałbym pokazać najprostszy sposób odczytania zawartości pliku xml
do kontrolki DataGridView.
Już nie będę pokazywał jak stworzyć projekt i dodać kontrolkę :).
Przejdę od razu do kodu. Jest to dosłownie 3 linijki kodu.
Ściągnąłem sobie dla wygody gdzieś z czeluści internetu przykładowy plik
xml i jego dla przykładu odczytałem.
No i efekt w gridzie:
Chciałbym pokazać najprostszy sposób odczytania zawartości pliku xml
do kontrolki DataGridView.
Już nie będę pokazywał jak stworzyć projekt i dodać kontrolkę :).
Przejdę od razu do kodu. Jest to dosłownie 3 linijki kodu.
Ściągnąłem sobie dla wygody gdzieś z czeluści internetu przykładowy plik
xml i jego dla przykładu odczytałem.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace XMLReader
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DataSet ds = new DataSet();
ds.ReadXml(@"c:\VS_ProjektyTestowe\XMLReader\XMLReader\cd_catalog.xml");
dataGridView1.DataSource = ds.Tables[0];
}
}
}
Jak widać nie kłamałem:)No i efekt w gridzie:
I to by było na tyle:)
sobota, 29 listopada 2014
Zegarek Binarny (Binary Watch)
Witajcie!
Dzisiaj chciałbym pokazać mały programik jakim jest zegarek binarny.
Zawsze chciałem taki mieć (przydało by się zrobić wersję elektroniczną) no i
troszkę czasu trzeba było poświęcić ale zegarek tyka i pokazuje binarnie
na wskaźnikach w postaci kropek pełną godzinę (24h), minuty oraz sekundy.
W programie również wyświetlana jest aktualna data lecz w zapisie
zero-jedynkowym.
Program oczywiście nabazgrany w c# :).
Jeśli ktoś będzie chciał to po uporządkowaniu kodu przedstawię go na blogu.
Poniżej przedstawia, krótkie video prezentacji zegarka.
Dzisiaj chciałbym pokazać mały programik jakim jest zegarek binarny.
Zawsze chciałem taki mieć (przydało by się zrobić wersję elektroniczną) no i
troszkę czasu trzeba było poświęcić ale zegarek tyka i pokazuje binarnie
na wskaźnikach w postaci kropek pełną godzinę (24h), minuty oraz sekundy.
W programie również wyświetlana jest aktualna data lecz w zapisie
zero-jedynkowym.
Program oczywiście nabazgrany w c# :).
Jeśli ktoś będzie chciał to po uporządkowaniu kodu przedstawię go na blogu.
Poniżej przedstawia, krótkie video prezentacji zegarka.
sobota, 22 listopada 2014
Robot dla każdego - part 3
Dzisiaj też króciutko na temat robota.
Robocik jest już autonomiczny potrafi określić drogę jazdy.
Czujnik HC-SR04, który umieściłem na serwie przekazuje dane na temat
odległości w 3 kierunkach (prosto, prawo, lewo). Po tym robot wie w którą stronę
ma jechać.
Dodatkowo dodałem dwie krańcówki po bokach, ale przydały by się im dłuższe wąsy.
Jako że płytka STM32F4 Discovery ma 4 diody użytkownika, to kiedy robot bada drogę
to wszystkie świecą na raz, a kiedy jedzie w wybranym kierunku świeci się dioda
odpowiednio jedna dioda.
Pod spodem filmik prezentujący jazdę robota w ograniczonym terenie.
W ostatniej części zamieszczę cały projekt w CooCox-ie. Więc, każdy będzie
mógł sobie wgrać wsad do swojej robota, ewentualnie dostosować do swoich potrzeb.
Robocik jest już autonomiczny potrafi określić drogę jazdy.
Czujnik HC-SR04, który umieściłem na serwie przekazuje dane na temat
odległości w 3 kierunkach (prosto, prawo, lewo). Po tym robot wie w którą stronę
ma jechać.
Dodatkowo dodałem dwie krańcówki po bokach, ale przydały by się im dłuższe wąsy.
Jako że płytka STM32F4 Discovery ma 4 diody użytkownika, to kiedy robot bada drogę
to wszystkie świecą na raz, a kiedy jedzie w wybranym kierunku świeci się dioda
odpowiednio jedna dioda.
Pod spodem filmik prezentujący jazdę robota w ograniczonym terenie.
W ostatniej części zamieszczę cały projekt w CooCox-ie. Więc, każdy będzie
mógł sobie wgrać wsad do swojej robota, ewentualnie dostosować do swoich potrzeb.
środa, 12 listopada 2014
Robot - dla każdego part2
Witam!
Wstępne testy robota się powiodły, więc pod spodem zamieszczam filmik z jego pierwszej jazdy.
Nie jest to jeszcze ostateczny soft, który będzie w nim zaimplementowany. Docelowo będzie
badał obszar przed sobą i wybierał drogę po której ma jechać. Dlatego czujnik HC-SR04 jest
umieszczony na servie, które będzie sterowane w trzech kierunkach.
Wstępne testy robota się powiodły, więc pod spodem zamieszczam filmik z jego pierwszej jazdy.
Nie jest to jeszcze ostateczny soft, który będzie w nim zaimplementowany. Docelowo będzie
badał obszar przed sobą i wybierał drogę po której ma jechać. Dlatego czujnik HC-SR04 jest
umieszczony na servie, które będzie sterowane w trzech kierunkach.
sobota, 8 listopada 2014
Robot - dla każdego!
Witajcie!
Na pewno każdy z nas zawsze marzył o zbudowaniu własnego robota.
Dzisiaj napiszę jedynie wstęp o tym jak zbudować własnego robota, który może
być sterowany bezprzewodowo.
Chociaż mój na tą chwile jest jeszcze w częściach i nawet nie ma sterowania bezprzewodowo
tylko przez UART to jednak chciałem się z wami podzielić tym co na tą chwile
zostało zrobione.
Jako podwozie użyłem zwykłego laminatu akurat dwustronny się poniewierał więc
zrobiłem z niego użytek.
Do napędu robota są użyte serwa SG90 przerobione na silniki czyli wywalona
blokada i odpięty potencjometr. Jako że posiadam drukarkę 3D to koła sobie wydrukowałem i uchwyty trzymające serwa. Wy możecie użyć kół od zabawki a uchwyty zrobić
np ze zlutowanego laminatu i będzie też trzymać. A jeśli nie to wykorzystać kawałki
blaszek i odpowiednio pozaginać i przykręcić do podwozia.
Robot będę zasilał z akumulatorków, do tego przygotowałem właśnie kopertę
na 4 akumulatorki. Szału nie będzie i wiadomo że długo one nie wytrzymają. Ale
nie mam na tą chwile żadnego pakietu li-pol.
Driver L298N do silników kupiłem za 20zł na alle.... więc tanio
Cały robot będzie sterowany z STM32F4 discovery akurat mam pod ręką. Wy
możecie użyć jakiejkolwiek płytki i procka bądź w ramach ćwiczeń projektowych
zaprojektować w eaglu coś dla siebie.
Koszty:
- dwa serwa SG90 - około 22zł - ja akurat miałem.
- Driver L298N - też około 20zł to już nawet z przesyłką (cała płytka wraz z radiatorem)
- koperta na akumulatorki - około 2zł
Aha docelowo robot będzie miał czujnik HC-SR04 (8zł) i może coś jeszcze wymyśle :)
Kiedy będzie w pełni gotowy to przedstawię cały soft do płytki jak również apke na PC
z której go będę sterował.
Na pewno każdy z nas zawsze marzył o zbudowaniu własnego robota.
Dzisiaj napiszę jedynie wstęp o tym jak zbudować własnego robota, który może
być sterowany bezprzewodowo.
Chociaż mój na tą chwile jest jeszcze w częściach i nawet nie ma sterowania bezprzewodowo
tylko przez UART to jednak chciałem się z wami podzielić tym co na tą chwile
zostało zrobione.
Jako podwozie użyłem zwykłego laminatu akurat dwustronny się poniewierał więc
zrobiłem z niego użytek.
Do napędu robota są użyte serwa SG90 przerobione na silniki czyli wywalona
blokada i odpięty potencjometr. Jako że posiadam drukarkę 3D to koła sobie wydrukowałem i uchwyty trzymające serwa. Wy możecie użyć kół od zabawki a uchwyty zrobić
np ze zlutowanego laminatu i będzie też trzymać. A jeśli nie to wykorzystać kawałki
blaszek i odpowiednio pozaginać i przykręcić do podwozia.
Robot będę zasilał z akumulatorków, do tego przygotowałem właśnie kopertę
na 4 akumulatorki. Szału nie będzie i wiadomo że długo one nie wytrzymają. Ale
nie mam na tą chwile żadnego pakietu li-pol.
Driver L298N do silników kupiłem za 20zł na alle.... więc tanio
Cały robot będzie sterowany z STM32F4 discovery akurat mam pod ręką. Wy
możecie użyć jakiejkolwiek płytki i procka bądź w ramach ćwiczeń projektowych
zaprojektować w eaglu coś dla siebie.
Koszty:
- dwa serwa SG90 - około 22zł - ja akurat miałem.
- Driver L298N - też około 20zł to już nawet z przesyłką (cała płytka wraz z radiatorem)
- koperta na akumulatorki - około 2zł
Aha docelowo robot będzie miał czujnik HC-SR04 (8zł) i może coś jeszcze wymyśle :)
Kiedy będzie w pełni gotowy to przedstawię cały soft do płytki jak również apke na PC
z której go będę sterował.
piątek, 5 września 2014
C# - Bindowanie danych do DataGridView
Witajcie
Dzisiaj króciutko pokażemy sobie jak bindować dane do kontrolki DataGridView.
Więc do dzieła.
Tworzymy nowy projekt WinFormsowy i dodajemy jeden button i kontrolkę
DataGridView z sekcji Data paska ToolBar.
Teraz dodajemy jeszcze jedną klasę, w której stworzymy listę osób oraz jedną
metodę. Klasę nazwiemy przykładowo "BindingClass".
Przechodzimy do zdarzenia buttona i tutaj napiszemy 3 linijki kodu, które nam załatwią
bindowanie danych.
i jako argument przekazujemy metodę ListaDanych klasy Bindingdata, która nam zwraca
kolekcję osób. Teraz zostało tylko do kontrolki DataGridView przypisać nasze dane
i to wszystko :).
Tym samym sposobem oddzieliliśmy warstwę interfejsu użytkownika od danych.
Całość wygląda mniej więcej tak:
Zachęcam do własnych testów.
I to było by na tyle w dzisiejszym wpisie. Powodzenia.
Dzisiaj króciutko pokażemy sobie jak bindować dane do kontrolki DataGridView.
Więc do dzieła.
Tworzymy nowy projekt WinFormsowy i dodajemy jeden button i kontrolkę
DataGridView z sekcji Data paska ToolBar.
Całość powinna wyglądać mniej więcej tak.
Teraz utworzymy klasę Person w której zdefiniujemy kilka właściwości określające
cechy osoby.
PPM klikamy na projekt i dodajemy klasę, którą nazywamy Person.
W klasie definiujemy trzy właściwości:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataGridView_Test
{
public class Person
{
public int ID { get; set; }
public string Imie { get; set; }
public string Nazwisko { get; set; }
}
}
Jak widzimy kodu bardzo mało - i generalnie o to nam chodzi.Teraz dodajemy jeszcze jedną klasę, w której stworzymy listę osób oraz jedną
metodę. Klasę nazwiemy przykładowo "BindingClass".
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataGridView_Test
{
public class BindingClass
{
//lista osób
private List person = new List
{ new Person { ID = 1, Imie = "Wilie", Nazwisko = "Coyote"},
new Person { ID = 2, Imie = "Road", Nazwisko = "Runner"},
new Person { ID = 3, Imie = "Marysia", Nazwisko = "Sierotka"}
};
///
/// Metoda zwraca listę osób z kolekcji person
///
///
public List ListaDanych()
{
List list = new List();
foreach (var osoba in person)
{
list.Add(osoba);
}
return list;
}
}
}
Teraz pozostaje nam tylko zbindować dane z kontrolką DataGridView.Przechodzimy do zdarzenia buttona i tutaj napiszemy 3 linijki kodu, które nam załatwią
bindowanie danych.
private void button1_Click(object sender, EventArgs e)
{
BindingClass dane = new BindingClass();
BindingList bindingLista = new BindingList(dane.ListaDanych());
dataGridView1.DataSource = bindingLista;
}
Najpierw tworzymy obiekt "dane" klasy BindingClass, następnie tworzymy binding-listęi jako argument przekazujemy metodę ListaDanych klasy Bindingdata, która nam zwraca
kolekcję osób. Teraz zostało tylko do kontrolki DataGridView przypisać nasze dane
i to wszystko :).
Tym samym sposobem oddzieliliśmy warstwę interfejsu użytkownika od danych.
Całość wygląda mniej więcej tak:
Zachęcam do własnych testów.
I to było by na tyle w dzisiejszym wpisie. Powodzenia.
niedziela, 24 sierpnia 2014
Regex Tester - wyrażenia regularne C#
Witajcie!
Chyba jak każdy programista czy to procesorów czy aplikacji na PC przyszło mi się
zmierzyć z prawidłowym wyłuskaniem danych z dokumentu tekstowego (excel, txt itp), ale
także z parsowaniem nadlatujących danych z procka.
I tutaj jeśli chodzi o procesory to sprawa jest trudniejsza ponieważ nie wiemy dokładnie
jakie dane nam nadlecą, czy wystąpią błędy w transmisji, czy ramka będzie cała, a w
komunikacji bezprzewodowej to już całkiem może być różnie.
Ja miałem problemy z komunikacją po RS485 w swoim robocie gdzie ogrom danych
był wysyłany z czujników jak również były wysyłane komendy sterujące pracą robota
(robot przemysłowy) i tutaj często zamiast poprawnych danych dostawałem
dziwne litery w ciągu cyfr.
Wiadomo można zaimplementować sprawdzenie danych CRC itp, ale można też w inny
sposób i ten sposób chciałbym omówić.
Wyjściem z tej trudnej sytuacji może być zaimplementowanie w naszym programie klasy Regex.
Regex przeszukuje łańcuchy znakowe w oparciu o określona strukturę czyli maskę.
Jednym słowem jeśli na wejście podamy łańcuch tekstowy to regex w oparciu o maskę
przefiltruje tekst i wypluje na wyjście tylko to co potrzebujemy.
Na nasze potrzeby napisałem program który pokaże to o czym napisałem powyżej.
Chyba jak każdy programista czy to procesorów czy aplikacji na PC przyszło mi się
zmierzyć z prawidłowym wyłuskaniem danych z dokumentu tekstowego (excel, txt itp), ale
także z parsowaniem nadlatujących danych z procka.
I tutaj jeśli chodzi o procesory to sprawa jest trudniejsza ponieważ nie wiemy dokładnie
jakie dane nam nadlecą, czy wystąpią błędy w transmisji, czy ramka będzie cała, a w
komunikacji bezprzewodowej to już całkiem może być różnie.
Ja miałem problemy z komunikacją po RS485 w swoim robocie gdzie ogrom danych
był wysyłany z czujników jak również były wysyłane komendy sterujące pracą robota
(robot przemysłowy) i tutaj często zamiast poprawnych danych dostawałem
dziwne litery w ciągu cyfr.
Wiadomo można zaimplementować sprawdzenie danych CRC itp, ale można też w inny
sposób i ten sposób chciałbym omówić.
Wyjściem z tej trudnej sytuacji może być zaimplementowanie w naszym programie klasy Regex.
Regex przeszukuje łańcuchy znakowe w oparciu o określona strukturę czyli maskę.
Jednym słowem jeśli na wejście podamy łańcuch tekstowy to regex w oparciu o maskę
przefiltruje tekst i wypluje na wyjście tylko to co potrzebujemy.
Na nasze potrzeby napisałem program który pokaże to o czym napisałem powyżej.
Program jest bardzo porosty i intuicyjny. W pierwszym polu tekstowym wpisujemy
ciąg tekstowy do sprawdzenia czy wyłuskania danych. W drugim polu tekstowym
piszemy naszą maskę względem której program przefiltruje tekst, a w ostatnim polu
dostajemy nasz wynik końcowy.
Ok to teraz przykład:
Powiedzmy, że zrobiliśmy komunikacje z naszym urządzeniem i z procesora dostajemy
dane takiej treści - 4598;1267;100
Są to np: dane z czujników i enkodera (tak dla przykładu tylko) i teraz powiedzmy, że
komunikacja coś szwankuje i dostajemy w naszym ciągu coś takiego 45q8;1267;100.
Jeśli robimy jakiś wykres w naszym programie to dostaniemy bzdury lub program się
nam wysypie podczas parsowania, że otrzymany ciąg nie jest liczbą i co teraz?
Teraz to się tylko załamać i wywalić kompa przez okno - heh żarcik!
Teraz to skorzystamy z naszego testera masek i zrobimy taką maskę, że wszelkie
inne dane których nie chcemy to nie dostaniemy:) - proste!
W pierwszym polu wpisaliśmy nasze dane, w drugim zaś naszą maskę po której ma fitrować
dane przychodzące z procesora. W trzecim polu tekstowym otrzymaliśmy komunikat o
pasujących dopasowaniach (czyli maska jest poprawna) i co najlepsze to jeszcze pogrupowane
dane czyli cóż więcej chcieć:).
Ale ktoś zapyta co to za ślaczki wpisał gościu i gada, że to działa - heh już tłumaczę.
- ^ - daszek oznacza że zaczynamy przeszukiwać wyrażenie od początku wiersza
- \d - dopasowujemy dowolną cyfrę dziesiętną {1,} a tutaj ile ma być występień tych cyfr
czyli więcej niż jedna, można napisać np: {4} i tylko dopasuje nam 4 cyfry ni mniej
ni więcej
-; - czyli w ciągu musi po cyfrach wystąpić znak średnika
Dalej maska się powtarza. Więc proste:)
Jak wspomniałem wcześniej możemy takimi maskami odfiltrować całe skoroszyty excela z danych
bardzo szybko i wyłuskać tylko takie jakie nas interesują.
Zastanówcie się ile trzeba było by pisać kodu jeśli trzeba było by robić if-y splity itp.
Link do programu.
Zachęcam do testowania i implementacji regexa w swoich aplikacjach
czwartek, 24 lipca 2014
AVR Timer Konfigurator - konfigurator trybów timerów w procesorach AVR
Witajcie!
Śledząc fora internetowe zauważyłem, że wiele początkujących osób ma problemy
z konfiguracją trybów timerów w procesorach AVR.
Wychodząc naprzeciw tym osobom napisałem program wspomagający konfigurację
podstawowych trybów takich jak "Normal, CTC i FastPWM".
Teraz dzięki AVR Timer Konfiguratorowi w prosty i szybki sposób będziesz w
stanie skonfugurować dowolny timer w trybie jaki potrzebujesz.
W programie wystarczy wybrać:
- procesor w jakim aktualnie konfigurujemy timer (wersja DEMO - tylko ATmega8)
- numer timera
- rezonator kwarcowy
- tryb timera np: Normal, CTC, FastPWM
- prescaler
- wpisać pożądaną częstotliwość w Hz (hercach)
Po wstępnej szybkiej konfiguracji wystarczy kliknąć przycisk "Przelicz" i otrzymamy
kod konfiguracji timera oraz blok kodu wektora obsługi przerwania jeśli występuje.
Wygenerowany kod można sobie przekopiować do np: Eclipse. :)
Jeśli zauważycie jakieś błędy w konfiguracji trybów proszę napiszcie mi na maila bądź w
komentarzu.
W linku zamieszczam narazie wersję DEMO programu, którym działa konfiguracja
tylko dla procesora ATmega8.
Link do programu:
Update:
Dodałem nowe procesory czyli teraz są aktywne:
- Atmega8
- Atmega88
- Atmega16
- Atmega32
Zachęcam do testowania programu i ewentualnego zgłaszania błędów.
Śledząc fora internetowe zauważyłem, że wiele początkujących osób ma problemy
z konfiguracją trybów timerów w procesorach AVR.
Wychodząc naprzeciw tym osobom napisałem program wspomagający konfigurację
podstawowych trybów takich jak "Normal, CTC i FastPWM".
Teraz dzięki AVR Timer Konfiguratorowi w prosty i szybki sposób będziesz w
stanie skonfugurować dowolny timer w trybie jaki potrzebujesz.
W programie wystarczy wybrać:
- procesor w jakim aktualnie konfigurujemy timer (wersja DEMO - tylko ATmega8)
- numer timera
- rezonator kwarcowy
- tryb timera np: Normal, CTC, FastPWM
- prescaler
- wpisać pożądaną częstotliwość w Hz (hercach)
Po wstępnej szybkiej konfiguracji wystarczy kliknąć przycisk "Przelicz" i otrzymamy
kod konfiguracji timera oraz blok kodu wektora obsługi przerwania jeśli występuje.
Wygenerowany kod można sobie przekopiować do np: Eclipse. :)
rys. Tryb Normal - Atmega8
rys. Tryb CTC - Atmega8
rys. Tryb FastPWM - Atmega8
W bliskiej przyszłości i o ile będzie zainteresowanie zaimplementuje do programu
tryby konfiguracji takich peryferii jak:
- UART
- SPI
- I2C
komentarzu.
W linku zamieszczam narazie wersję DEMO programu, którym działa konfiguracja
tylko dla procesora ATmega8.
Link do programu:
Update:
Dodałem nowe procesory czyli teraz są aktywne:
- Atmega8
- Atmega88
- Atmega16
- Atmega32
Zachęcam do testowania programu i ewentualnego zgłaszania błędów.
sobota, 21 czerwca 2014
STM32F429i - PWM + LED
Witajcie!
Jako kontynuację artykułów o STM32F429i przedstawię sposób płynnej
regulacji świecenia diodą led.
Do naszej zabawy będziemy potrzebować przejściówkę FT232, ponieważ
zmodyfikujemy nasz terminal, który wspomoże nas w płynnej regulacji
wypełnienia PWM, oraz diodę led wraz z rezystorem około 300 ohm.
PWM - czyli Pulse Width Modulation - jest to modulacja szerokości impulsu
utworzonego np: na "wyjściu" naszego timera, który jest tak skonfigurowany aby
generował sygnał prostokątny. My zaś zmieniając parametry modulujemy
tzw. wypełnienie czyli szerokość, tym samym zmieniając wartość średnią
napięcia. Oczywiście nie możemy zapomnieć o bardzo ważnym parametrze
jakim jest częstotliwość naszego przebiegu prostokątnego. Częstotliwość tą
ustawiłem na 1kHz.
Dla lepszego zobrazowania o co chodzi przedstawię screeny z oscyloskopu,
w którym zmienię wartość wypełnienia co z kolei wpłynie na wartość średnią
napięcia na pinie mikrokontrolera.
PWM - 25% -Uavg = 768mV f= 1kHz
Na koniec zostaje nam pokazanie jak wszystko wspólnie działa. Na filmie będzie
ładnie widać jak płynnie zmienia się wartość PWM a dioda led czerwona zmienia
jasność.
Przyjemnej zabawy :)
Jako kontynuację artykułów o STM32F429i przedstawię sposób płynnej
regulacji świecenia diodą led.
Do naszej zabawy będziemy potrzebować przejściówkę FT232, ponieważ
zmodyfikujemy nasz terminal, który wspomoże nas w płynnej regulacji
wypełnienia PWM, oraz diodę led wraz z rezystorem około 300 ohm.
PWM - czyli Pulse Width Modulation - jest to modulacja szerokości impulsu
utworzonego np: na "wyjściu" naszego timera, który jest tak skonfigurowany aby
generował sygnał prostokątny. My zaś zmieniając parametry modulujemy
tzw. wypełnienie czyli szerokość, tym samym zmieniając wartość średnią
napięcia. Oczywiście nie możemy zapomnieć o bardzo ważnym parametrze
jakim jest częstotliwość naszego przebiegu prostokątnego. Częstotliwość tą
ustawiłem na 1kHz.
Dla lepszego zobrazowania o co chodzi przedstawię screeny z oscyloskopu,
w którym zmienię wartość wypełnienia co z kolei wpłynie na wartość średnią
napięcia na pinie mikrokontrolera.
PWM - 25% -Uavg = 768mV f= 1kHz
PWM - 50% -Uavg = 1,5V f= 1kHz
PWM - 75% -Uavg = 2.25V f= 1kHz
Na oscylogramach widać ładnie jak zmienia się wypełnienie i tym samym wartość
średnia napięcia.
Oczywiście PWM możemy regulować np: prędkość obrotową silnika, nic nie stoi na
przeszkodzie :). W kolejnych cyklach pokażemy sobie jak sterować serwami
modelarskimi :) co przydaje się każdemu elektronikowi chcącemu zbudować własnego
robota.
Ok najpierw zajmijmy się kodem C# naszego terminala ponieważ dodałem kontrolkę
TrackBara, którą regulujemy płynnie wypełnienie.
private void trackBar1_Scroll(object sender, EventArgs e)
{
serialPort1.Write(trackBar1.Value.ToString() + "\r");
}
Wygląd naszej formatki powinien wyglądać w taki sposób:
Widzimy że kod jest banalny. W zdarzeniu event_scroll TrackBara za każdym przesunięciem
wskaźnika wysyłamy wartość na COM od 0 - 512.
Ok to teraz przejdźmy do trudniejszych rzeczy. Przedstawię kod pliku main.c
#include "main.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "stm32_ub_uart.h"
#include "stdlib.h"
void Init(void);
void Delay(volatile uint32_t nCount);
void initPWM(void);
void strreverse(char* begin, char* end);
int main(void)
{
UART_RXSTATUS_t check;
char rx_buf[RX_BUF_SIZE];
SystemInit();
Init(); //inicjalizacja diody - do tego ćwiczenia nie potrzebna
initPWM(); //inicjalizacja timera 5, który pracuje w trybie PWM
UB_Uart_Init(); //inicalizacja USARTA
uint16_t i = 0;
while(1)
{
check=UB_Uart_ReceiveString(COM1,rx_buf); //zapisujemy odebrane dane do bufora
if(check==RX_READY) { //sprawdzamy czy dane zostały odebrane
i = atol(rx_buf); //konwertujemy dane z bufora czyli ascii na int
TIM_SetCompare1(TIM5, i); //timer pwm - zapisujemy odebraną wartosc już skonwertowaną do timera
UB_UART_SendInt(COM1,i,10); //wysylamy spowrotem odebraną wartosc
//UB_Uart_SendString(COM1,rx_buf);
UB_Uart_SendString(COM1,"\r\n"); //wysylamy znak powrotu karetki i nowej lini
}
//Delay(5000000);
}
}
void initPWM()
{
/* TIM5 włączenie zegara */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Obliczenie wartoci preskalera */
uint16_t u16PrescalerValue = (uint16_t) ((SystemCoreClock) / 1000000)- 1;
TIM_TimeBaseStructure.TIM_Prescaler = u16PrescalerValue; // 1MHz - preskaler
TIM_TimeBaseStructure.TIM_Period = 500; // 1 MHz / 500 /2 = 1kHz (1ms)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //licznik zlicza w góre
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //inicjalizacja struktury Timera 5
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //tryb pwm
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //odpalenie timera
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
/*********************TIM5**************************/
/* konfiguracja trybu PWM: kanał 1 (GPIOA Pin 0)*/
TIM_OC1Init(TIM5, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable );
TIM_Cmd(TIM5, ENABLE); //odpalenie timera
///////////////konfuguracja GPIO ///////////////
GPIO_InitTypeDef GPIO_PWM;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PWM.GPIO_Mode = GPIO_Mode_AF;
GPIO_PWM.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_PWM.GPIO_OType = GPIO_OType_PP;
GPIO_PWM.GPIO_PuPd = GPIO_PuPd_UP;
//PORT A Pin0
GPIO_PWM.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_PWM);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM5 );
Myślę, że komentarze pomogą w zrozumieniu kodu.Na koniec zostaje nam pokazanie jak wszystko wspólnie działa. Na filmie będzie
ładnie widać jak płynnie zmienia się wartość PWM a dioda led czerwona zmienia
jasność.
Przyjemnej zabawy :)
poniedziałek, 16 czerwca 2014
C# - Baza Danych (edit) - cz.4
Witajcie!
Dzisiaj będzie kontynuacja wątku o bazie danych. Pokażemy sobie jak zrobić możliwość
edycji naszych danych.
No to do dzieła!
Przeciągamy z ToolBoxa button i zmieniamy mu "content" w kodzie XAML na Edytuj,
oraz "Name" na "btnEdit".
Ok. jeśli dołożyliśmy nasz button i zmieniliśmy jego parametry, to klikamy dwa razy
na niego i przechodzi do zdarzenia kliknięcia.
Tam stworzymy nowy obiekt klasy Baza oraz wywołamy metodę "EditaData" do, której
przekażemy parametry takie jak: nazwę naszej kontrolki DataGridView, numer wiersza do
edycji, nazwę naszego textBoxa z imieniem, oraz nazwę textBoxa z nazwiskiem.
to w zdarzeniu nasz kod sprowadza się raptem do 4 linijek.
Co my tu mamy?.
Tworzymy nowy obiekt klasy Baza gdzie w konstruktorze przekazujemy ścieżkę
do naszej bazy danych. Następnie wywołujemy metodę, która woła aby jej zapodać
nazwę naszej kontrolki DataGridView, numer wiersza jaki został wybrany mychą,
textBox w który wpisujemy Imię oraz drugi z Nazwiskiem. Ostatnia linijka to funkcja
która robi update naszej kolekcji w gridzie.
Ok teraz przejdźmy do naszej klasy Baza.
W kodzie naszej klasy dodajemy metodę EdytujDane, której nadajemy atrybut public
oraz nie zwracamy nic czyli typ void.
połączenia z bazą, również tworzymy obiekt typu DataAdapter - obiekt ten reprezentuje zestaw
poleceń do połączenia z bazą danych jak również manipulacji na tychże danych.
W następnej linijce wywołujemy zapytanie query do naszej bazy danych, gdzie ustawiamy
do Imienia przypisujemy zmienną Imię a do Nazwiska nazwisko.
W następnych linijka jest do naszych edytowanych wierszy przekazywana wartość imienia i nazwiska
które są parametrem metody. dalej otwieramy połączenie, wykonujemy polecenie query i natychmiast
połączenie to zamykamy.
Zrobiłem jeszcze małą modyfikację poprzednich metod, wywaliłem z tamtą odświeżanie
grida i zrobiełm z tego metodę, którą wywołujemy po dodaniu, usunięciu czy edycji danych.
Kod klasy Baza.cs
Jeśli będziecie mieć jakieś pytania to śmiało piszcie!!
Dzisiaj będzie kontynuacja wątku o bazie danych. Pokażemy sobie jak zrobić możliwość
edycji naszych danych.
No to do dzieła!
Przeciągamy z ToolBoxa button i zmieniamy mu "content" w kodzie XAML na Edytuj,
oraz "Name" na "btnEdit".
Ok. jeśli dołożyliśmy nasz button i zmieniliśmy jego parametry, to klikamy dwa razy
na niego i przechodzi do zdarzenia kliknięcia.
Tam stworzymy nowy obiekt klasy Baza oraz wywołamy metodę "EditaData" do, której
przekażemy parametry takie jak: nazwę naszej kontrolki DataGridView, numer wiersza do
edycji, nazwę naszego textBoxa z imieniem, oraz nazwę textBoxa z nazwiskiem.
private void btnEdit_Click(object sender, RoutedEventArgs e)
{
Baza b1 = new Baza(@"Data Source = Baza.sdf");
b1.EditData(dg, numerWiersza, txtImie.Text, txtNazwisko.Text);
MessageBox.Show("Edytowano");
b1.UpdateGrid(dg);
}
Ok. Jak widać dzięki temu że cały kod metody do edycji jest zawarty w naszej klasieto w zdarzeniu nasz kod sprowadza się raptem do 4 linijek.
Co my tu mamy?.
Tworzymy nowy obiekt klasy Baza gdzie w konstruktorze przekazujemy ścieżkę
do naszej bazy danych. Następnie wywołujemy metodę, która woła aby jej zapodać
nazwę naszej kontrolki DataGridView, numer wiersza jaki został wybrany mychą,
textBox w który wpisujemy Imię oraz drugi z Nazwiskiem. Ostatnia linijka to funkcja
która robi update naszej kolekcji w gridzie.
Ok teraz przejdźmy do naszej klasy Baza.
W kodzie naszej klasy dodajemy metodę EdytujDane, której nadajemy atrybut public
oraz nie zwracamy nic czyli typ void.
public void EditData(DataGrid dg, int RowNumber, string imie, string nazwisko)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
da = new SqlCeDataAdapter();
da.UpdateCommand = new SqlCeCommand("UPDATE Pracownicy SET Imie=@Imie, Nazwisko=@Nazwisko WHERE ID = @ID", cn);
da.UpdateCommand.Parameters.Add("@Imie", SqlDbType.NVarChar).Value = imie;
da.UpdateCommand.Parameters.Add("@Nazwisko", SqlDbType.NVarChar).Value = nazwisko;
da.UpdateCommand.Parameters.Add("@ID",SqlDbType.Int).Value = RowNumber;
cn.Open();
da.UpdateCommand.ExecuteNonQuery();
cn.Close();
}
W pierwszej kolejności tworzymy obiekt cn, gdzie w konstruktorze przekazujemy stringpołączenia z bazą, również tworzymy obiekt typu DataAdapter - obiekt ten reprezentuje zestaw
poleceń do połączenia z bazą danych jak również manipulacji na tychże danych.
W następnej linijce wywołujemy zapytanie query do naszej bazy danych, gdzie ustawiamy
do Imienia przypisujemy zmienną Imię a do Nazwiska nazwisko.
W następnych linijka jest do naszych edytowanych wierszy przekazywana wartość imienia i nazwiska
które są parametrem metody. dalej otwieramy połączenie, wykonujemy polecenie query i natychmiast
połączenie to zamykamy.
Zrobiłem jeszcze małą modyfikację poprzednich metod, wywaliłem z tamtą odświeżanie
grida i zrobiełm z tego metodę, którą wywołujemy po dodaniu, usunięciu czy edycji danych.
public void UpdateGrid(DataGrid dg)
{
da = new SqlCeDataAdapter();
dt = new DataTable();
dg.ItemsSource = dt.DefaultView;
da.Update(dt); //update grida
}
Całość teraz wygląda tak:
Kod klasy Baza.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.Data;
using System.Windows;
using System.Windows.Controls;
namespace WPF_Baza
{
public class Baza
{
private static string _conn;
public SqlCeDataAdapter da;
public DataTable dt;
///
/// konstruktor
///
///
public Baza(string conn)
{
_conn = conn;
}
///
/// dodawanie danych do bazy
///
public void InsertData(string Imie, string Nazwisko)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
da = new SqlCeDataAdapter();
da.InsertCommand = new SqlCeCommand("INSERT INTO Pracownicy(Imie, Nazwisko) VALUES(@Imie, @Nazwisko)", cn);
da.InsertCommand.Parameters.Add("@Imie", SqlDbType.NVarChar).Value = Imie;
da.InsertCommand.Parameters.Add("@Nazwisko", SqlDbType.NVarChar).Value = Nazwisko;
cn.Open();
da.InsertCommand.ExecuteNonQuery();
cn.Close();
MessageBox.Show("Dodano do bazy!");
}
///
/// wyświetlanie danych z bazy
///
public void ShowData(DataGrid dg)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
dt = new DataTable();
da = new SqlCeDataAdapter();
da.SelectCommand = new SqlCeCommand("SELECT * FROM Pracownicy", cn);
dt.Clear();
da.Fill(dt);
dg.ItemsSource = dt.DefaultView;
da.Update(dt);
}
///
/// usuwanie danych z bazy
///
public void DeleteData(DataGrid dg, int RowNumber)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
da = new SqlCeDataAdapter();
da.DeleteCommand = new SqlCeCommand("DELETE FROM Pracownicy WHERE ID = @ID", cn);
da.DeleteCommand.Parameters.Add("@ID", SqlDbType.Int).Value = RowNumber; //usunięcie numeru wiersza przekazanego jako parametr do metody
cn.Open();
da.DeleteCommand.ExecuteNonQuery();
cn.Close();
}
public void EditData(DataGrid dg, int RowNumber, string imie, string nazwisko)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
da = new SqlCeDataAdapter();
da.UpdateCommand = new SqlCeCommand("UPDATE Pracownicy SET Imie=@Imie, Nazwisko=@Nazwisko WHERE ID = @ID", cn);
da.UpdateCommand.Parameters.Add("@Imie", SqlDbType.NVarChar).Value = imie;
da.UpdateCommand.Parameters.Add("@Nazwisko", SqlDbType.NVarChar).Value = nazwisko;
da.UpdateCommand.Parameters.Add("@ID",SqlDbType.Int).Value = RowNumber;
cn.Open();
da.UpdateCommand.ExecuteNonQuery();
cn.Close();
}
public void UpdateGrid(DataGrid dg)
{
da = new SqlCeDataAdapter();
dt = new DataTable();
dg.ItemsSource = dt.DefaultView;
da.Update(dt); //update grida
}
}
}
Ok to by było na tyle w tym odcinku.Jeśli będziecie mieć jakieś pytania to śmiało piszcie!!
piątek, 6 czerwca 2014
STM32F429i-Discovery USART_LED_TOG + C#
Witajcie!
W ostatnim odcinku o STM32F429i opowiedzieliśmy sobie jak odpalić uarta
na naszej płytce. Dzisiaj chciałbym troszkę zmodyfikować nasz kod a raczej
dodać do niego mruganie diodami, ale nie za pomocą micro-switcha a zrobić
sterowanie za pomocą naszego terminala, w którym dodamy sobie taką możliwość.
Będziemy wysyłać literkę przez port COM na naszą płytkę co spowoduje
zapale się diody.
Oczywiście nie użyjemy tam żadnych sztucznych opóźnień. Zrobimy to tak jak
należy:).
Kod to mrugania diody oczywiście znajduje się w jednym z poprzednich postów
wprowadzających do opisu naszej płytki STM32F429i i to ten kod użyjemy.
Ale najpierw uzbroimy nasz terminal w możliwość wysyłania własnych
znaków (stringów) przez port COM.
Jeszcze zanim dodamy przyciski do wysyłania naszych znaków, wstawimy
sobie buttonik do czyszczenia terminalu, tego w sumie mi brakowało
podczas pracy z tym terminalem.
A więc metoda drag&drop przeciągamy na naszą formatkę z ToolBoxa
buton i zmieniamy mu nazwę na "btnClear" oraz nazwę, która będzie wyświetlana
na nim na "Wyczyść".
Klikamy ppm na buttonie i przechodzimy do zdarzenia kliknięcia, w którym
napiszemy kod do wyczyszczenia tekstu z "richTextBox1".
płytce.
Nazwiemy odpowiednio "btnRed i btnGreen", jak nazwa wskazuje jeden będzie
odpowiadał za mruganie diodą zieloną a drugi czerwoną.
Aby nasze butony ładnie wyglądały po odpaleniu naszego terminala
zmienimy im kolory.
W zdarzeniu Form1_Load dodajemy kod:
zielony i czerwony.
Wstępnie terminal powinien wyglądać tak:
OK. Jeśli mamy dodane nasze butony to oprogramujemy sobie ich zdarzenia kliknięcia.
W przyszłości dodamy sobie możliwości wysyłania stringów zdefiniowanych przez nas,
co będzie bardziej uniwersalnym rozwiązaniem.
Ok teraz przejdziemy do kodu w C jaki zapodamy do naszego procka:
W pętli głównej odbieramy literkę "r lub g" i po odebraniu po prostu zmieniamy
stan naszych diod na przeciwny.
Jeszcze krótki film pokazujący działanie naszego terminala i mruganie diodkami
na Discovery.
Link do pliku exe terminala.
Przyjemnej zabawy
W ostatnim odcinku o STM32F429i opowiedzieliśmy sobie jak odpalić uarta
na naszej płytce. Dzisiaj chciałbym troszkę zmodyfikować nasz kod a raczej
dodać do niego mruganie diodami, ale nie za pomocą micro-switcha a zrobić
sterowanie za pomocą naszego terminala, w którym dodamy sobie taką możliwość.
Będziemy wysyłać literkę przez port COM na naszą płytkę co spowoduje
zapale się diody.
Oczywiście nie użyjemy tam żadnych sztucznych opóźnień. Zrobimy to tak jak
należy:).
Kod to mrugania diody oczywiście znajduje się w jednym z poprzednich postów
wprowadzających do opisu naszej płytki STM32F429i i to ten kod użyjemy.
Ale najpierw uzbroimy nasz terminal w możliwość wysyłania własnych
znaków (stringów) przez port COM.
Jeszcze zanim dodamy przyciski do wysyłania naszych znaków, wstawimy
sobie buttonik do czyszczenia terminalu, tego w sumie mi brakowało
podczas pracy z tym terminalem.
A więc metoda drag&drop przeciągamy na naszą formatkę z ToolBoxa
buton i zmieniamy mu nazwę na "btnClear" oraz nazwę, która będzie wyświetlana
na nim na "Wyczyść".
Klikamy ppm na buttonie i przechodzimy do zdarzenia kliknięcia, w którym
napiszemy kod do wyczyszczenia tekstu z "richTextBox1".
private void btnClear_Click(object sender, EventArgs e)
{
richTextBox1.Clear(); //czyszczenie richtexboxa
}
Teraz możemy sobie dodać dwa buttony do sterowania diodami na naszej płytce.
Nazwiemy odpowiednio "btnRed i btnGreen", jak nazwa wskazuje jeden będzie
odpowiadał za mruganie diodą zieloną a drugi czerwoną.
Aby nasze butony ładnie wyglądały po odpaleniu naszego terminala
zmienimy im kolory.
W zdarzeniu Form1_Load dodajemy kod:
private void Form1_Load(object sender, EventArgs e)
{
btnGreen.BackColor = Color.Green;
btnRed.BackColor = Color.Red;
}
Podczas ładowania okna kolor tła naszych przycisków będzie miał odpowiedniozielony i czerwony.
Wstępnie terminal powinien wyglądać tak:
OK. Jeśli mamy dodane nasze butony to oprogramujemy sobie ich zdarzenia kliknięcia.
private void btnRed_Click(object sender, EventArgs e)
{
serialPort1.WriteLine("r\n\r");
}
private void btnGreen_Click(object sender, EventArgs e)
{
serialPort1.WriteLine("g\n\r");
}
Generalnie jeśli chodzi o nasz terminal to będzie na dzień dzisiejszy tyle modyfikacji.W przyszłości dodamy sobie możliwości wysyłania stringów zdefiniowanych przez nas,
co będzie bardziej uniwersalnym rozwiązaniem.
Ok teraz przejdziemy do kodu w C jaki zapodamy do naszego procka:
#include "main.h"
#include "stm32_ub_uart.h"
void Diody_Init(void);
void Delay(volatile uint32_t nCount);
int main(void)
{
UART_RXSTATUS_t check;
char rx_buf[RX_BUF_SIZE];
SystemInit();
// inicjalizacja UART (COM1 : TX=PA9, RX=PA10)
UB_Uart_Init();
Diody_Init();
while(1)
{
check=UB_Uart_ReceiveString(COM1,rx_buf);
if(check==RX_READY) {
if(rx_buf[0] == 'g')
{
GPIOG->ODR ^= GPIO_Pin_13; // led_tog red
}else if(rx_buf[0] == 'r')
{
GPIOG->ODR ^= GPIO_Pin_14; // led_tog green
}
}
}
}
void Diody_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// włączenie zegara
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); //ustawienie zegara
// ustawienie pinów portu G
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG, &GPIO_InitStructure);
}
void Delay(volatile uint32_t nCount) { // funkcja opóźniająca
while(nCount--)
{
}
}
Myślę że kod jest czytelny i nie wymaga jakiegoś większego tłumaczenia.W pętli głównej odbieramy literkę "r lub g" i po odebraniu po prostu zmieniamy
stan naszych diod na przeciwny.
Jeszcze krótki film pokazujący działanie naszego terminala i mruganie diodkami
na Discovery.
Link do pliku exe terminala.
Przyjemnej zabawy
sobota, 31 maja 2014
STM32F429i-discovery -UART
Witajcie!
Dzisiaj sobie przedstawimy chyba najbardziej popularny sposób komunikacji
procka z otoczeniem - w naszym przypadku będzie to płytka STM32F429i- Discovery + przejściówka FT232RL, a dane powędrują na terminal, który został opisany w jednym z postów wcześniej.
Protokołu komunikacji RS232 oczywiście nie będę tutaj opisywał jest tego masa w necie,
wujek google wyświetli masę wiadomości o tym.
Ramka oczywiście będzie wyglądała standardowo 8n1 - czyli 8 bitów danych, bez bitów parzystości
z jednym bitem stopu. Prędkość transmisji ustawimy sobie na 115200 (baudrate).
Jeśli chodzi o nasza płytkę to zawiera ona 8 uartów, my skorzystamy z pierwszego. Piny
nadawczy i odbiorczy są na porcie A odpowiednio TX - PA9, RX - PA10. I tak należy
podpiąć przewodzikami nasz zestaw z przejściówką USB/RS232 FT232RL.
Aha ważna informacja - standard napięć jakie panują na pinach naszej płytki to 3,3V,
należy o tym pamiętać!!!.
Link do projektu w CooCoxie zamieszczę na końcu artykułu, będzie sobie go można
pobrać i testować.
Generalnie omówię tutaj plik main.c. Pliki uart.h i uart.c będą zawierały komentarze
więc będzie się można lepiej z nimi zapoznać.
Na początku deklarujemy funkcję, która wprowadzi nam opóźnienie do wysyłania
informacji na terminal. W ciele tej funkcji po każdym biegu pętli odliczamy wartość
jaką wprowadzamy do niej jako parametr.
Zmianna typu UART_RXSTATUS_t określa status bufora, w tej części artykułu
jeszcze nie będzie nam potrzebna. Następnie deklarujemy nasz bufor odbiorczy.
Jest on wielkości 50 bajtów. Jego rozmiar określa się w pliku uart.h. W pętli
głównej co około 100ms wysyłamy string "WITAJ ŚWICIE" zakończony znakami
powrotu karetki oraz nowej linii,
Dzisiaj sobie przedstawimy chyba najbardziej popularny sposób komunikacji
procka z otoczeniem - w naszym przypadku będzie to płytka STM32F429i- Discovery + przejściówka FT232RL, a dane powędrują na terminal, który został opisany w jednym z postów wcześniej.
Protokołu komunikacji RS232 oczywiście nie będę tutaj opisywał jest tego masa w necie,
wujek google wyświetli masę wiadomości o tym.
Ramka oczywiście będzie wyglądała standardowo 8n1 - czyli 8 bitów danych, bez bitów parzystości
z jednym bitem stopu. Prędkość transmisji ustawimy sobie na 115200 (baudrate).
Jeśli chodzi o nasza płytkę to zawiera ona 8 uartów, my skorzystamy z pierwszego. Piny
nadawczy i odbiorczy są na porcie A odpowiednio TX - PA9, RX - PA10. I tak należy
podpiąć przewodzikami nasz zestaw z przejściówką USB/RS232 FT232RL.
Aha ważna informacja - standard napięć jakie panują na pinach naszej płytki to 3,3V,
należy o tym pamiętać!!!.
Link do projektu w CooCoxie zamieszczę na końcu artykułu, będzie sobie go można
pobrać i testować.
Generalnie omówię tutaj plik main.c. Pliki uart.h i uart.c będą zawierały komentarze
więc będzie się można lepiej z nimi zapoznać.
#include "main.h"
#include "stm32_ub_uart.h"
void Delay(volatile uint32_t nCount);
int main(void)
{
UART_RXSTATUS_t check;
char rx_buf[RX_BUF_SIZE];
SystemInit();
// inicjalizacja UART (COM1 : TX=PA9, RX=PA10)
UB_Uart_Init();
while(1)
{
}
UB_Uart_SendString(COM1, "WITAJ SWIECIE\r\n");
Delay(10000000);
}
}
void Delay(volatile uint32_t nCount) { // funkcja opóźniająca
while(nCount--)
{
}
}
Jak widać plik jest bardzo czytelny i nie zawiera wiele kodu.Na początku deklarujemy funkcję, która wprowadzi nam opóźnienie do wysyłania
informacji na terminal. W ciele tej funkcji po każdym biegu pętli odliczamy wartość
jaką wprowadzamy do niej jako parametr.
Zmianna typu UART_RXSTATUS_t określa status bufora, w tej części artykułu
jeszcze nie będzie nam potrzebna. Następnie deklarujemy nasz bufor odbiorczy.
Jest on wielkości 50 bajtów. Jego rozmiar określa się w pliku uart.h. W pętli
głównej co około 100ms wysyłamy string "WITAJ ŚWICIE" zakończony znakami
powrotu karetki oraz nowej linii,
W następnej części zmodyfikujemy nasz kod w pętli głównej, tak aby po wysłaniu
odpowiedniej komendy np: literki "a" zaświeciła nam się dioda na naszej płytce.
Oczywiście modyfikacji będzie wymagał nasz terminal. Dodamy mu funkcję wysyłania
danych za pomocą buttona.
Link to projektu.
Przyjemnej zabawy:)
poniedziałek, 26 maja 2014
C# - Baza Danych (show and delete) - cz.3
W poprzednim odcinku pokazaliśmy sobie jak wprowadzić dane do naszej bazy
oraz stworzyliśmy klasę "Baza.cs" i utworzyliśmy konstruktor oraz
metodę pozwalającą dodawać dane.
Dzisiaj napiszemy metody, które to wprowadzone dane do bazy wyświetlą nam
w kontrolce DataGrid oraz usuną z bazy.
.
No to jedziemy:). Z "ToolBoxa" przeciągamy na nasze główne okno kontrolkę
"DataGrid", oraz buton i nazywamy odpowiednio "dg" oraz "btnShow".
hm... teraz pasuje się zastanowić jak dobrać się do grida z poziomu kasy,
ponieważ pasuje tak zmontować nasza klasę dalej, aby metody, które w niej
implementujemy były najbardziej uniwersalne jak to tylko możliwe a kod w głównym
oknie był jak najbardziej uproszczony.
Aby tego dokonać musimy przekazać jako parametr do naszej metody
"ShowData" obiekt typu DataGrid. najlepiej będzie to widać w kodzie:
podpinamy DataTable.
Komentarza wymaga myślę jeszcze zapytanie query:
z tabeli "Pracownicy".
Moglibyśmy zrobić to też w taki sposób "SELECT * FROM Pracownicy",
w tym przypadku efekt był by taki sam z tym, że jeszcze dostalibyśmy
kolumnę z numerami ID. Użycie gwiazdki powoduje wybranie wszystkich
dostępnych kolumn z tabeli "Pracownicy". Myślę że reszta kodu jest zrozumiała.
Natomiast w zdarzeniu buttona napiszemy sobie taki o to krótki kod:
do naszej bazy i wyświetlić buttonem "Wyświetl". Efekt powinien
być podobny do tego na obrazku poniżej.
Przechodzimy do okienka Properties i klikamy na nasz GridView po czym
w zakładce properties wybieramy zakładkę "Events" i odszukujemy zdarzenie
"SelectedCellsChangedeventHendler" i klikamy dwa razy co zaowocuje stworzenie
kodu zdarzenia kliknięcia.
przechowywać dla nas wartość komórki ID naszego delikwenta w bazie przez
co będziemy mieć pewność, że taki a nie inny został usunięty.
przeszukujemy GridView w poszukiwaniu zaznaczonego wiersza w kolumnie ID.
Teraz przejdźmy do pliku klasy gdzie zaimplementujemy metodę która usuwa
wybrany element z grida a co za tym idzie z bazy.
"WHERE" i to tutaj precyzujemy po jakim indeksie będziemy usuwać dane. Najbezpieczniej
jest właśnie usuwać po numerze ID, ponieważ jeśli byśmy chcieli usunąć po imieniu bądź
nazwisku przypadkiem usunęlibyśmy nie tą osobę jaką chcieliśmy.
Ostatnią rzeczą jaką nam pozostała jest kod zdarzenia przycisku "Usuń". Trzymając
się założeń że całą robotę ma odwalać metoda w naszej klasie a kod w głównym
oknie ma być jak najbardziej czytelny to tak uczynimy pisząc tylko trzy linijki.
Więc klikamy dwa razy na nasz buton co spowoduje utworzenie kodu zdarzenia
kliknięcia buttona i wklepujemy kodzik:
dostępu do bazy. Obiekt posiada metodę "DeleteData", która to jako parametry
przyjmuje nazwę naszego grida oraz numer wiersza który ma zostać usunięty
i to wszystko. :)
Jeszcze update kodu naszej klasy:
W następnej części opiszemy metodę edycji naszych danych w bazie:)
a może uda się coś jeszcze zrobić.
oraz stworzyliśmy klasę "Baza.cs" i utworzyliśmy konstruktor oraz
metodę pozwalającą dodawać dane.
Dzisiaj napiszemy metody, które to wprowadzone dane do bazy wyświetlą nam
w kontrolce DataGrid oraz usuną z bazy.
.
No to jedziemy:). Z "ToolBoxa" przeciągamy na nasze główne okno kontrolkę
"DataGrid", oraz buton i nazywamy odpowiednio "dg" oraz "btnShow".
hm... teraz pasuje się zastanowić jak dobrać się do grida z poziomu kasy,
ponieważ pasuje tak zmontować nasza klasę dalej, aby metody, które w niej
implementujemy były najbardziej uniwersalne jak to tylko możliwe a kod w głównym
oknie był jak najbardziej uproszczony.
Aby tego dokonać musimy przekazać jako parametr do naszej metody
"ShowData" obiekt typu DataGrid. najlepiej będzie to widać w kodzie:
public void ShowData(DataGrid dg)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
dt = new DataTable();
da = new SqlCeDataAdapter();
da.SelectCommand = new SqlCeCommand("SELECT Imie, Nazwisko FROM Pracownicy", cn);
dt.Clear();
da.Fill(dt);
dg.ItemsSource = dt.DefaultView;
da.Update(dt);
}
Widzimy tutaj, że jako parametr przekazujemy obiekt tupu DataGrid i do gridapodpinamy DataTable.
Komentarza wymaga myślę jeszcze zapytanie query:
da.SelectCommand = new SqlCeCommand("SELECT Imie, Nazwisko FROM Pracownicy", cn);
A więc, poleceniem "SELECT" zaznaczamy kolumny jakie chcemy wyświetlićz tabeli "Pracownicy".
Moglibyśmy zrobić to też w taki sposób "SELECT * FROM Pracownicy",
w tym przypadku efekt był by taki sam z tym, że jeszcze dostalibyśmy
kolumnę z numerami ID. Użycie gwiazdki powoduje wybranie wszystkich
dostępnych kolumn z tabeli "Pracownicy". Myślę że reszta kodu jest zrozumiała.
Natomiast w zdarzeniu buttona napiszemy sobie taki o to krótki kod:
Baza b1 = new Baza(@"Data Source = Baza.sdf"); //tworzymy nowy obiekt naszej klasy Baza
b1.ShowData(this.dg); //odpalamy metodę ShowData i przekazujemy jako parametr nazwę naszego grida
Teraz możemy odpalić nasz program oraz wprowadzić kilku pracowników do naszej bazy i wyświetlić buttonem "Wyświetl". Efekt powinien
być podobny do tego na obrazku poniżej.
Ok, teraz stworzymy sobie przycisk do usuwania danych z bazy. W tym celu
przeciągamy sobie z "ToolBoxa" buttona i w widoku kodu XAML zmienimy
właściwość "Content" na "Usuń" oraz właściwość "Name" na "btnDel".Przechodzimy do okienka Properties i klikamy na nasz GridView po czym
w zakładce properties wybieramy zakładkę "Events" i odszukujemy zdarzenie
"SelectedCellsChangedeventHendler" i klikamy dwa razy co zaowocuje stworzenie
kodu zdarzenia kliknięcia.
Zanim przejdziemy do kodu zdarzenia utworzymy zmienna globalną, która będzieprzechowywać dla nas wartość komórki ID naszego delikwenta w bazie przez
co będziemy mieć pewność, że taki a nie inny został usunięty.
private int numerWiersza;Teraz przechodzimy do zdarzenia "SelectedCellsChanged" i w pętli foreach
przeszukujemy GridView w poszukiwaniu zaznaczonego wiersza w kolumnie ID.
private void dg_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
foreach (DataRowView dgv in dg.SelectedItems)
{
numerWiersza = Convert.ToInt32( dgv[0]); //zapisanie do zmiennej numerWiersza wartości z pod kolumny ID
}
}
Zmienna "dvg" jest typu "DataGrid" więc musimy ją przekonwertować na inta.Teraz przejdźmy do pliku klasy gdzie zaimplementujemy metodę która usuwa
wybrany element z grida a co za tym idzie z bazy.
public void DeleteData(DataGrid dg, int RowNumber)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
da = new SqlCeDataAdapter();
dt = new DataTable();
da.DeleteCommand = new SqlCeCommand("DELETE FROM Pracownicy WHERE ID = @ID", cn);
da.DeleteCommand.Parameters.Add("@ID", SqlDbType.Int).Value = RowNumber; //usunięcie numeru wiersza przekazanego jako parametr do metody
cn.Open();
da.DeleteCommand.ExecuteNonQuery();
cn.Close();
dg.ItemsSource = dt.DefaultView;
da.Update(dt); //update grida
}
Polecenie query usuwa dane z bazy które są filtrowane za pomocą słowa kluczowego "WHERE" i to tutaj precyzujemy po jakim indeksie będziemy usuwać dane. Najbezpieczniej
jest właśnie usuwać po numerze ID, ponieważ jeśli byśmy chcieli usunąć po imieniu bądź
nazwisku przypadkiem usunęlibyśmy nie tą osobę jaką chcieliśmy.
Ostatnią rzeczą jaką nam pozostała jest kod zdarzenia przycisku "Usuń". Trzymając
się założeń że całą robotę ma odwalać metoda w naszej klasie a kod w głównym
oknie ma być jak najbardziej czytelny to tak uczynimy pisząc tylko trzy linijki.
Więc klikamy dwa razy na nasz buton co spowoduje utworzenie kodu zdarzenia
kliknięcia buttona i wklepujemy kodzik:
private void btnDel_Click(object sender, RoutedEventArgs e)
{
Baza b1 = new Baza(@"Data Source = Baza.sdf");
b1.DeleteData(dg, numerWiersza);
MessageBox.Show("Usunięto!");
}
W ciele zdarzenia tworzymy nowy obiekt naszej klasy oraz podajemy ścieżkędostępu do bazy. Obiekt posiada metodę "DeleteData", która to jako parametry
przyjmuje nazwę naszego grida oraz numer wiersza który ma zostać usunięty
i to wszystko. :)
Jeszcze update kodu naszej klasy:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.Data;
using System.Windows;
using System.Windows.Controls;
namespace WPF_Baza
{
public class Baza
{
private static string _conn;
public SqlCeDataAdapter da;
public DataTable dt;
///
/// konstruktor
///
///
public Baza(string conn)
{
_conn = conn;
}
///
/// dodawanie danych do bazy
///
public void InsertData(string Imie, string Nazwisko)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
da = new SqlCeDataAdapter();
da.InsertCommand = new SqlCeCommand("INSERT INTO Pracownicy(Imie, Nazwisko) VALUES(@Imie, @Nazwisko)", cn);
da.InsertCommand.Parameters.Add("@Imie", SqlDbType.NVarChar).Value = Imie;
da.InsertCommand.Parameters.Add("@Nazwisko", SqlDbType.NVarChar).Value = Nazwisko;
cn.Open();
da.InsertCommand.ExecuteNonQuery();
cn.Close();
MessageBox.Show("Dodano do bazy!");
}
///
/// wyświetlanie danych z bazy
///
public void ShowData(DataGrid dg)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
dt = new DataTable();
da = new SqlCeDataAdapter();
da.SelectCommand = new SqlCeCommand("SELECT * FROM Pracownicy", cn);
dt.Clear();
da.Fill(dt);
dg.ItemsSource = dt.DefaultView;
da.Update(dt);
}
///
/// usuwanie danych z bazy
///
public void DeleteData(DataGrid dg, int RowNumber)
{
SqlCeConnection cn = new SqlCeConnection(_conn);
da = new SqlCeDataAdapter();
dt = new DataTable();
da.DeleteCommand = new SqlCeCommand("DELETE FROM Pracownicy WHERE ID = @ID", cn);
da.DeleteCommand.Parameters.Add("@ID", SqlDbType.Int).Value = RowNumber; //usunięcie numeru wiersza przekazanego jako parametr do metody
cn.Open();
da.DeleteCommand.ExecuteNonQuery();
cn.Close();
dg.ItemsSource = dt.DefaultView;
da.Update(dt); //update grida
}
}
}
Wszystko działa przyjemnie i miło. Zachęcam do testów:)W następnej części opiszemy metodę edycji naszych danych w bazie:)
a może uda się coś jeszcze zrobić.
Subskrybuj:
Posty (Atom)










