I am currently doing a project in school where me and my group are supposed to make the game "Bomberman" and execute it on a STM32F4-Discovery card (which has an ARM based processor on it). The game is displayed on a small LCD touchscreen that is connected to the discovery card, the touchscreen is also used as the controller for the game. The game is playable as of now, everything executes correctly and you can play alone against three AI-characters. The game and all hardware initiations are written entirely in C.
Now we have decided we want to implement multiplayer in the game, meaning we will have two setups of STM32F4-Discovery cards and LCD touchscreens. Each setup controls one player on the same game map. We are supposed to connect the two setups through USART.
My question is, how do we make these two STM32F4-Discovery cards communicate and display the same game map? I've tried to google it without any success so I now turn to you at stackoverflow.
EDIT: I am adding a follow up question in the light of the information provided by Unwind.
Follow up question:
We got a lot of pre-written files that we could use to initiate our hardware etc. One of these files are called STM32F4xx-usart.c. It contains a function:
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct).
The USART_InitStruct looks like this (it was pre-defined in the code that we got):
typedef struct{
uint32_t USART_BaudRate;
uint16_t USART_WordLength;
uint16_t USART_StopBits;
uint16_t USART_Parity;
uint16_t USART_Mode;
uint16_t USART_HardwareFlowControl;
} USART_InitTypeDef;
I am guessing I will have to use this structure to form two new structs that will hold the values for my master card and my slave card.
My question is: How do I write these two structs so that I can pass it to the init_USART() function?
You don't need to provide any values, only the syntax.
I tried
struct USART1_initStruct{
uint32_t USART_BaudRate;
uint16_t USART_WordLength;
uint16_t USART_StopBits;
uint16_t USART_Parity ;
uint16_t USART_Mode ;
uint16_t USART_HardwareFlowControl;
} U1IS = {9600, USART_WordLength_9b, USART_StopBits_1, USART_Parity_No, USART_Mode_Tx, USART_HardwareFlowControl_None};
and then passing this struct to the function, but I got an error:
error: expected expression before 'struct'
Make one of the boards the master, and the other the slave.
The job of the master (or server) is to run the game and decide what happens. The role of the slave (or client) is to display the world view to its local player, send input to the master and receive updates on the game's objects.
You can also view it as two slaves, connected to a single master which also happens to run on the same physical machine as one of the slaves.
It's not going to be very simple, especially since it sounds as if you didn't design for this from the beginning which usually helps.
USART_InitTypeDef x;
x.BaudRate = 9600;
x.WordLength = USART_WordLength_9b;
... etc
USART_Init(USART1,&x);
Look at any of the example code provided by STM.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
New to PIC programming or just programming in general. Wondering how I can display a number on the 7 segment display that corresponds to the number of times the push button at RA5 is pressed. E.g press button 2 times = number 2 displayed and if it's pressed 10 times, the count resets to 0. Any help is appreciated
What do you mean this question is too broad?
Tom, first off, to help you out in the future:
According to the "closed" info. box on the question, this question was closed because it "needs to be more focused", and it should be updated "so it focuses on one problem only." I'd like to help you know what that means from my perspective.
I didn't vote to close it, but in this case I totally understand why it was closed.
It's too broad. You showed no coding attempt whatsoever and you asked what you thought was a very focused question, but which actually is too broad because there is too much to cover here. With you writing no code whatsoever, the questions within your question might include the following:
How do you write C at all?
How do you set up a main() function?
What's a function?
What's a variable?
What's a signed vs unsigned variable?
How do you do bare-metal multi-tasking?
How do you program a PIC microcontroller?
What are hardware registers and how do you use them?
How do you configure pins as inputs vs outputs?
How do you read pin states?
How do you write to pins?
How do you do bitwise operations to set an entire output port (all pins to the display) all at once instead of one-at-a-time?
How does electricity work?
What does it mean to write a pin to output LOW vs ouput HIGH vs input?
What's a pullup resistor?
What's an LED array? How do you drive one?
Are the LEDs in the 7-segment display turned on by writing the pin to output HIGH or output LOW (ie: do we need to source from or sink to the pins to light up the LEDs)?
How do displays work and how do you control them?
I originally didn't see the circuit diagram until I edited the question to make the image show up, so I at first I also needed this information and thought we may need to cover the following:
Does the 7-segment display have its own on-board driver IC and require I2C, SPI, or asynchronous RS-232-style TTL logic level Serial commands to drive it instead?
How do displays work and how do you control them?
What is Persistence of Vision (PoV) and how might it apply?--in particular if driving multiple digits (multiple 7-segment displays)
Do we need to consider multiplexing so you can control more 7-Segment digits with fewer pins?
Do we need to consider Charlieplexing to use fewer pins still than standard multiplexing?
Anyway, let me get you started. The concept for your circuit is pretty straightforward.
Here is how your circuit works:
Each segment on the display is turned on by setting the appropriate pin to output LOW, since Vcc (probably 5V) is connected to the other side of the LEDs. So, to turn on segment a, you'd set RC0 to output LOW, to turn on segment b, you'd set RC1 to output LOW, etc. Since all of your LEDs in this display share a common Vcc (usually 5V) pin, this is a common anode 7-segment display. Since each of the 7 LEDs in the display has its own dedicated pin, you can light up any of the LEDs at one time, rather than having to round-robbin through them in a multiplexed or Charliplexed fashion.
If you wish to add another digit (another 7-segment display), you can double the number of required pins from 7 to 14, OR you can multiplex the new display, moving Vcc of each display to its own pin, and sharing the 7 segment pins RC0 through RE2. Therefore, 2 displays can take 14 pins if not multiplexed, or 9 pins if multiplexed. OR, if you have a common-anode and a common-cathode 7-segment display, you can Charlieplex them, hooking up each individual LED together and the common anode of one display and the common cathode of the other display together on another pin, thereby getting away with only 8 pins for 2 displays--the direction of current would set which display gets lit up. Round-robbining through the displays to refresh them, thereby relying on our eyes' persistence of vision trait, would be required for both multiplexing and Charlieplexing.
You read the RA5 button presses by seeing when RA5, an input pin, goes LOW. Since the button grounds the pin, and the pin has an external pullup resistor on it, HIGH means the button is NOT pressed, and LOW means it is pressed. Be sure to debounce this button press in software or else a single button press may register as dozens or even hundreds of button presses, depending on the mechanics of the button.
That's the circuit.
Here is how the program logic works:
The logic is pretty straightforward too: each time you read a debounced button press, increment a counter. Output the digit on the 7-segment display according to the counter. Example: to write a 2, you'd turn on segments a, b, g, e, and d. You can look at the display to figure out the other numbers.
Sample source code outline to get you started:
#include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C
#include <stdint.h> // For `uint8_t`, `int8_t`, etc.
// Read the pin to look for button presses and return true if the
// **debounced** button changes indicate the button has been pressed once
bool buttonWasPressedOnce()
{
// you do this
}
// Write a number 0 to 9 to the display
void writeDisplay(uint8_t number)
{
// you do this
}
// set up your PIC peripherals, input/output pin states, etc, here
void setup()
{
// you do this
}
// your main program logic goes here; this runs repeatedly, forever
void loop()
{
static uint8_t button_pressed_count = 0;
if (buttonWasPressedOnce())
{
button_pressed_count++;
// roll over after 9 back to 0
if (button_pressed_count > 9)
{
button_pressed_count = 0;
}
}
writeDisplay(button_pressed_count);
}
int main()
{
setup();
while (true)
{
loop();
}
return 0;
}
References and additional reading, including sample libraries to look at:
Here is some Arduino code to get you started, to see various options. Port it to your PIC microcontroller: https://www.instructables.com/Different-methods-of-driving-7-Segment-LED-display/
Sample library to study as a reference: https://github.com/DeanIsMe/SevSeg
You'll also need to know button debouncing, and a ton of other skills. Example debouncing: https://www.arduino.cc/en/Tutorial/BuiltInExamples/Debounce
my own debounce library I wrote for Arduino a long time ago: https://www.electricrcaircraftguy.com/2014/05/ercaguybuttonreader-library-for-arduino.html and https://github.com/ElectricRCAircraftGuy/eRCaGuy_ButtonReader and https://github.com/ElectricRCAircraftGuy/eRCaGuy_EventReader
https://www.allaboutcircuits.com/technical-articles/driving-led-arrays-with-an-arduino/
https://www.google.com/search?q=led+array&oq=led+array&aqs=chrome..69i57j69i65.2207j0j7&sourceid=chrome&ie=UTF-8
https://www.sparkfun.com/products/retired/13795
great video: https://www.youtube.com/watch?v=ohewJ9sTfwM
https://en.wikipedia.org/wiki/Multiplexed_display
https://en.wikipedia.org/wiki/Charlieplexing
https://en.wikipedia.org/wiki/Three-state_logic
https://en.wikipedia.org/wiki/Persistence_of_vision
https://en.wikipedia.org/wiki/Seven-segment_display
Using Windows API, I want to implement something like following:
i.e. Getting current microphone input level.
I am not allowed to use external audio libraries, but I can use Windows libraries. So I tried using waveIn functions, but I do not know how to process audio input data in real time.
This is the method I am currently using:
Record for 100 milliseconds
Select highest value from the recorded data buffer
Repeat forever
But I think this is way too hacky, and not a recommended way. How can I do this properly?
Having built a tuning wizard for a very dated, but well known, A/V conferencing applicaiton, what you describe is nearly identical to what I did.
A few considerations:
Enqueue 5 to 10 of those 100ms buffers into the audio device via waveInAddBuffer. IIRC, when the waveIn queue goes empty, weird things happen. Then as the waveInProc callbacks occurs, search for the sample with the highest absolute value in the completed buffer as you describe. Then plot that onto your visualization. Requeue the completed buffers.
It might seem obvious to map the sample value as follows onto your visualization linearly.
For example, to plot a 16-bit sample
// convert sample magnitude from 0..32768 to 0..N
length = (sample * N) / 32768;
DrawLine(length);
But then when you speak into the microphone, that visualization won't seem as "active" or "vibrant".
But a better approach would be to give more strength to those lower energy samples. Easy way to do this is to replot along the μ-law curve (or use a table lookup).
length = (sample * N) / 32768;
length = log(1+length)/log(N);
length = max(length,N)
DrawLine(length);
You can tweak the above approach to whatever looks good.
Instead of computing the values yourself, you can rely on values from Windows. This is actually the values displayed in your screenshot from the Windows Settings.
See the following sample for the IAudioMeterInformation interface:
https://learn.microsoft.com/en-us/windows/win32/coreaudio/peak-meters.
It is made for the playback but you can use it for capture also.
Some remarks, if you open the IAudioMeterInformation for a microphone but no application opened a stream from this microphone, then the level will be 0.
It means that while you want to display your microphone peak meter, you will need to open a microphone stream, like you already did.
Also read the documentation about IAudioMeterInformation it may not be what you need as it is the peak value. It depends on what you want to do with it.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm making a robot that should have simple two way communication for a large variety of values to a desktop via UART (serial communication, modem port). It's also desirable for it to be easy to add new values.
The board on the robot is an Olimexino, a rather powerful Arduino clone with an arm processor. For the sake of simplicity, I believe it could be affordable to store all relevant global values as floats.
My idea is to store all values in a matrix, like below. On the robot I for instance would like multiple controllers, which here can be viewed just as a heap of values grouped. These should be easy to modify and send.
enum rows
{
controller_a,
controller_b,
controller_c,
rows
}
enum controllers
{
controller_value1,
controller_value2,
columns
}
float values[rows][columns]
This should make it quite easy to for instance add a controller. It would also be rather easy to send and insert values, as I could target any vale by just sending the coordinates as [row, column].
The question is though, are there other better ways?
Should I perhaps define the controllers in structs instead
struct controller
{
float controller_value1;
etc
}controllers[columns];
If I make sure that all controllervalues are floats, maybe I could use pointers to the structs for easy read/write? I dont't know how to do that pointer aritmethics though. I guess it would require a specific routine for handling each different struct, meaning that the code wouldnt be that easy to modify?
First, it is a very very bad idea to use floats if you are going to be sending the data between devices, particularly if they are going to be of different architectures, it would be far more sound to use 64 bit integers and implement a fixed point by hand where necessary. Floats are not of a predictable format in memory and thus trying to serialise them is highly difficult.
Second, I think you have some sound ideas as far as storing the data goes, using a 2D array of a fixed type to store the data will work well and hopefully be well optimised. The enums are also a nice way of avoiding confusion. However what you are missing is a way to send them easily. As you are using a micro a nice simple protocol would do, may I suggest something along the lines of the following. This assumes you are keeping the table synced between your computer and the arduino like:
uint64_t ValueTable[CONTROLLER_MAX][VALUE_MAX];
uint32_t UartFD; // This gets set somewhere during init
// It should be a non blocking fd so we dont block if there are
// no value changes
void SetValue(uint32_t ControllerNum, uint32_t ValueIndex, uint64_t Value)
{
ValueTable[ControllerNum][ValueIndex] = Value;
write(UartFD, &ControllerNum, sizeof(uint32_t));
write(UartFD, &ValueIndex, sizeof(uint32_t));
write(UartFD, &Value, sizeof(uint64_t));
}
void GetValue(void)]
{
uint32_t ContNum;
uint32_t ValIndx;
uint64_t Value;
if(!read(UartFD, &ContNum, sizeof(uint32_t)))
{
// No data waiting
return;
}
// Wait for the rest
while(!read(UartFD, &ValIndx, sizeof(uint32_t)));
while(!read(UartFD, &Value, sizeof(uint64_t)));
ValueTable[ContNum][ValIndx] = Value;
}
Obviously this is the version for the PC, the arduino needs read and write replaced with Serial.read and Serial.write and does not need the first argument, otherwise the two are the same.Obviously you need to call those wherever you write to a value in the table.
Effectively for what you are doing your idea is great, just make sure to keep the implementation fast and simple so it runs well on the robot's embedded system. Yuo need not worry too much about extensibility, as you are likely to update both at once, particularly if you can keep a fair amount of common code between the PC and robot.
I am trying to understand the fsa9485 driver(USB switch). there in dock initialization code I came across:
switch_dev_register(&switch_dock)
switch_dock is a structure of type switch_dev and in accessory detection routine it is used like:
switch_set_state(&switch_dock, attached)
I am inferring like : There are 2 types of dock one being car dock and other being desk dock and switch_dev class is for switching between them.
Why do we require switch_dev classes??. How that class differentiates between two different dock?
The switch_dev_register function registers a device with sysfs and creates files in /sys/. Switch_set_state updates the value in one of the created files on your running kernel (the state file). So in my kernel I can see the state by reading a file "/sys/devices/virtual/switch/dock/state." State is 1 for deskdock, 2 for cardock, and 0 otherwise. This is just a simple way of passing hardware information up to userspace.
It is necessary to use the switch_dev class for standardization in sysfs. The driver differentiates between the two docks by reading register values from the fsa9485 chip which resides on the I2C bus. See fsa9480_detect_dev in fsa9480.c where the driver reads values from an analog to digital converter (ADC) and a device type register to determine the type of dock.
I want to arrange an AI contest between some friends.
Lets say tic tac toe,
each player program a method which get the board and a symbol(X\O) and return the place which he want to play at his turn.
Now my problem its how to "connect" two AI's in another program so I can test all users and see who has the best code.
The only way I think of is to communicate with a text file - all the AI's have thread running on background and check changes on the text file,the engine summary the game details(which turn,the board,score,players) to the text file.
How can this can be done better?
And one more little thing, this is common to have a time frame for each turn in AI contests?
(Because the AI program will run in different times on different computers)
It isn't clear from your question whether this has to be performed online or not.
If you're after finding "the best Tic Tac Toe algorithm", you could simply:
(This may slightly differ, depending on the programming language)
Define an interface (e.g: ITicTacToeSolver)
Have all your friends implement it in their own way and send you a DLL with their solution.
Create the game which will dynamically load these DLLs, and test them (play 1,000,000 games with the algorithm that is loaded).
Keep track of game statistics to see which algorithm is best.
If the AI programs are competing in a game like tic tac toe, typically every program would have limited total "thinking" time (e.g. 5 minutes), and a program that exceeds its time allotment would lose.
Typically often the programs are connected over some sort of a simple protocol, not through text files. The protocol can run on standard I/O or through TCP/IP sockets.
To normalize CPU usage, you can request that for tournament games, all the programs are compiled to work on a reference platform and then you provide two identical PCs, both running one of the active contestants. It then becomes a requirement of your tournament that the programs can be executed on this reference platform.
Use an interface and a standard programming language - so you can forget about text files and bollocks like that.
Figure out a simple SOAP protocol. You can simply create a WSDL interface - easy to create using windows communication foundatoin (WCF) or JMS.
Easiest would be to have a centralized server to serve as a referee and keep track of time. Each player could be assigned an ID.
Then you could have a the following interface (use WCF or JMS to create a WSDL SOAP protocol)
function int requestGame(int opponentID, int color)
- if called with color = -1, randomly assigns a color and returns it (0=white, 1=black).
- otherwise you can request a color, and returns it if accepted, -1 if not accepted.
- could use -1 to request random opponent.
function int getRemainingTime(int color)
- returns the time remaining on clock for color
function bool play(int color, int i, int j)
where color = 0 - white - 1 black,
i, j are board coordinates,
- returns true if it is a legal move
function bool won(int color)
- returns true if color has won the game.
Not having a centralized server would be more complex since they would have to negotiate over agreed wins, time, etc.
I would suggest to have each of the AI be executable files, communicating by using standard input and output. The game engine (the referee) would send the complete state of the world to AI_one as input, then wait for a move from standard output. It would then perform the move (if legal) and repeat the process for AI_two, then alternate between the two until the game is over. As a failsafe the referee can make one side lose if it takes too long to make a move.
This method is used by Google AI challenge.
One very big advantage to this approach is that people can write their AI in different languages, as long as they follow the agreed standard for how to make a move.
If your goal is to have an AI programming competition amongst friends, I'd suggest that you don't waste time designing and implementing the framework for holding the competition. Use something that already exists for that purpose. You can skip all the pain and heartache of fixing bugs in your framework and get right to the fun part: developing AI.
A good framework is the Robocode game. Watching your robots kill each other will be a lot more fun than watching them play tic-tac-toe.
You should take a look at this question:
What is the best Battleship AI?
In it he creates a battleship AI contest / challenge. It was very high rated and a lot of fun to code for and watch.
He used the Tournament API http://tournaments.codeplex.com/ to run the competition.
Also, it's important to allow the submissions to compete multiple times.. ie 1000 times each. This removes alot of the randomness and luck from the competitors.