Merge remote-tracking branch 'github/master'
This commit is contained in:
commit
dc3299f5f8
43 changed files with 6933 additions and 308 deletions
63
README.md
63
README.md
|
@ -2,17 +2,26 @@
|
|||
|
||||
You see an armed time bomb but don't know how to disarm it. Your friends found a manual to defuse the bomb and you have them on call. This is the premise of the game OBUS, a hardware project by [Zeus WPI](https://zeus.ugent.be). Inspired by the amazing software game [Keep Talking and Nobody Explodes](https://www.keeptalkinggame.com/).
|
||||
|
||||
# Get started writing a module
|
||||
## Get started writing a module
|
||||
|
||||
These are the instructions for building your own OBUS module with an Arduino Nano v3 and the custom PCB. If
|
||||
you're using other hardware, you might need to do some things differently.
|
||||
|
||||
0. Read the "[Getting started guide](docs/GETTING_STARTED.md)" to get a general idea of how OBUS works.
|
||||
1. [Install](https://www.arduino.cc/en/Guide/#install-the-arduino-desktop-ide) the Arduino IDE.
|
||||
2. Clone this repository with Git in a permanent location on your drive.
|
||||
3. Symlink the library: `ln -s /ABSOLUTE/PATH/TO/REPO/lib /PATH/TO/Arduino/libraries/obus`
|
||||
(on most Linux distro's, this the Arduino folder is in `$HOME/Arduino`)
|
||||
4. Follow [these steps](https://github.com/autowp/arduino-mcp2515/#software-usage) to install the CAN library
|
||||
5. Execute `./src/new_module.sh` to create a new module
|
||||
5. Execute `./src/new_module.sh` to create a new module. When asked for a type, you'll probably want to choose 'puzzle'.
|
||||
6. Edit the newly generated .ino file, either in the Arduino IDE or in your own editor.
|
||||
7. In the Arduino IDE, select the correct board (Arduino Nano) and processor (ATmega328P (Old Bootloader)). After that,
|
||||
flash your code to the Arduino and test it out.
|
||||
|
||||
# Background
|
||||
## Game
|
||||
TODO insert picture here
|
||||
|
||||
## Background
|
||||
### Game
|
||||
|
||||
The game is played by at least two players. The goal is to defuse a bomb,
|
||||
this is accomplished by defusing every module on that bomb before the bomb
|
||||
|
@ -25,49 +34,15 @@ There are two roles:
|
|||
|
||||
These two roles can communicate with each other. To successfully defuse the bomb, they must
|
||||
communicate efficiently and clearly. If a mistake is made, the team gets a strike.
|
||||
If they get too many strikes, the bomb explodes, even if the timer hasn't run out yet.
|
||||
If they get too many strikes or the timer runs out, the bomb explodes.
|
||||
|
||||
## Implementation details
|
||||
### Implementation goals
|
||||
|
||||
Now we want to implement this game in hardware. As in the computer version, we want this game to be modular:
|
||||
it should be easy to 1) make new modules and 2) attach them to a bomb. To do this, we need to settle on
|
||||
a protocol, both in hardware and in software.
|
||||
- It should be easy to add new modules, both hardware- and software-wise
|
||||
- It should be easy to build your own module and get it working with the rest of the game
|
||||
- Every run of the game should be different
|
||||
- It should be possible for multiple people at the same time to develop a new module
|
||||
|
||||
The idea is to have one bomb controller that keeps track of the timer, the amount of strikes and of whether
|
||||
the bomb has been successfully disarmed, and to have multiple modules that have one or more challenges on them
|
||||
that need to be solved.
|
||||
|
||||
### Hardware
|
||||
|
||||
The bomb controller and modules have to be able to communicate with each other. Ideally, we would like a hardware bus where it is easy to add more modules. We would also like to minimise the amount of wires that are needed.
|
||||
|
||||
Multiple protocols were considered:
|
||||
|
||||
- I2C: very standard, most microcontrollers have this built in; unfortunately, limited in the amount of nodes that can connect to the same network (255), limited in distance between nodes (about 1 meter), and the bus needs 4 wires (GND, VCC and two data lines)
|
||||
- SPI: needs even more wires, and requires a separate wire per module
|
||||
- Serial: this is not a bus architecture, so a lot of wires will need to be used
|
||||
|
||||
But eventually, CAN was picked. CAN is widely used in vehicles and has several desired properties:
|
||||
- We only need two wires (CAN uses a differential pair)
|
||||
- Distance can be up to 500m
|
||||
- There is built-in packet collision avoidance and per-node priorities
|
||||
- CAN modules are very cheap
|
||||
- There are existing Arduino libraries for the CAN module we'll be using
|
||||
|
||||
The payload of a CAN packet is 8 bytes long, this should be enough.
|
||||
|
||||
## Software
|
||||
|
||||
We needed to decide on a protocol to communicate between the bomb controller and the modules (and possibly also between modules?).
|
||||
|
||||
Some things we had to consider:
|
||||
|
||||
- payload is 8 bytes per packet
|
||||
- packets can be delayed or not received on every node, so detection of this and retransmission might be needed: if the bomb interactor solves a module and the packet that communicates this with the bomb does not get delivered to the controller, the bomb will still go off, even if all modules have been solved
|
||||
- we can't send an infinite amount of packets; the higher our bitrate is, the shorter our wires need to be
|
||||
|
||||
## Development setup
|
||||
|
||||
In the Arduino IDE, select the correct board (Arduino Nano) and processor (ATmega328P (Old Bootloader)).
|
||||
|
||||
We use [this](https://github.com/autowp/arduino-mcp2515/) library for CAN communications. See [this](https://github.com/autowp/arduino-mcp2515/#software-usage) header for 3 simple steps on how to use it in the arduino IDE
|
||||
|
|
|
@ -42,15 +42,17 @@ class Message:
|
|||
def sender_id(self):
|
||||
return (self.received_from >> 0) & 0b1111_1111
|
||||
|
||||
def human_readable_type(self):
|
||||
return [('controller' if self.sender_id() == 0 else 'info'), 'puzzle', 'needy', 'RESERVED TYPE'][self.sender_type()]
|
||||
@staticmethod
|
||||
def human_readable_type(sender_type, sender_id):
|
||||
return [('controller' if sender_id == 0 else 'info'), 'puzzle', 'needy', 'RESERVED TYPE'][sender_type]
|
||||
|
||||
def _parse_state_update(self):
|
||||
timeleft = self.payload[1] << 0x18 | self.payload[2] << 0x10 | self.payload[3] << 0x08 | self.payload[4]
|
||||
strikes = self.payload[5]
|
||||
max_strikes = self.payload[6]
|
||||
solved_puzzle_modules = self.payload[7]
|
||||
|
||||
return f'{timeleft/1000:3.2f} {strikes:02}/{max_strikes:02}'
|
||||
return f'{timeleft/1000:3.2f} {strikes:02}/{max_strikes:02} [{solved_puzzle_modules:02}]'
|
||||
|
||||
def parse_message(self):
|
||||
sender_type = self.sender_type()
|
||||
|
@ -58,7 +60,7 @@ class Message:
|
|||
try:
|
||||
if sender_type == 0b00 and self.sender_id() == 0: # controller
|
||||
if message_type == 0:
|
||||
return "ACK"
|
||||
return f"ACK {Message.human_readable_type(self.payload[1], self.payload[2])} {self.payload[2]}"
|
||||
elif message_type == 1:
|
||||
return "HELLO"
|
||||
elif message_type == 2:
|
||||
|
@ -99,7 +101,7 @@ class Message:
|
|||
'parsed': self.parse_message(),
|
||||
'pretty_raw_sender_id': f'{self.priority_bit():01b} {self.sender_type():02b} {self.sender_id():08b}',
|
||||
'raw_message': f"{self.payload.hex(' ')}",
|
||||
'human_readable_type': self.human_readable_type(),
|
||||
'human_readable_type': Message.human_readable_type(self.sender_type(), self.sender_id()),
|
||||
'sender_id': self.sender_id(),
|
||||
'internal_id': self.internal_id
|
||||
}
|
||||
|
|
123
docs/GETTING_STARTED.md
Normal file
123
docs/GETTING_STARTED.md
Normal file
|
@ -0,0 +1,123 @@
|
|||
# Getting started
|
||||
|
||||
This is a guide for writing your own puzzle module. We'll first start by
|
||||
describing an OBUS game, then describe the minimum things you need to implement
|
||||
to get a working puzzle module. We'll then finish by explaining some nice-to-haves
|
||||
(like using info modules or game state in a puzzle module).
|
||||
|
||||
## OBUS game
|
||||
|
||||
### Parts of the game
|
||||
|
||||
The goal of OBUS is to defuse a bomb by communicating clearly. There are (at least) two players: the defuser and the expert.
|
||||
The defuser can see and interact with the bomb, the expert can read the manual that describes how to defuse the bomb.
|
||||
You win the game by defusing the bomb, you lose if the bomb explodes. The bomb is defused when all puzzle modules are
|
||||
solved; the bomb explodes if the time runs out or too much mistakes ("strikes") have been made.
|
||||
|
||||
The bomb consists of a controller and multiple modules: the controller shows the time left, the amount of mistakes made
|
||||
while defusing the bomb (strikes) and the amount of strikes left. It's responsible for starting games, enumerating modules,
|
||||
keeping track of game state, ...
|
||||
The modules on the other hand are the parts of the bomb that can be interacted with by the defuser. There are several kinds of
|
||||
modules: puzzle modules, needy modules and info modules.
|
||||
|
||||
Puzzle modules are the most common kind of modules. The bomb is defused as soon as all puzzle modules are solved.
|
||||
Puzzle modules are generally solved by having the defuser observe some kind of state of the game, then having them
|
||||
communicate that information to the expert. The expert then uses this information and the manual to communicate a set of
|
||||
instructions to the defuser. If the instructions are correct and the defuser executes them correctly, the module is solved.
|
||||
If one of the two players makes an error and the defuser executes an incorrect action, the module generates a "strike".
|
||||
|
||||
An example of a puzzle module is an RGB led with a red and a green button under it. The defuser looks at the module and
|
||||
sees that the RGB led is colored blue. They then tell that to the expert, who then looks up this module in the manual.
|
||||
The manual instructs to press the green button if the color starts with the letter "b" or "o". The expert then asks the
|
||||
defuser to press the green button. When the defuser does this, the module is solved.
|
||||
|
||||
There are also needy modules. These can't be "solved", but they can generate strikes: they require periodic action
|
||||
from the defuser to prevent them from generating a strike.
|
||||
|
||||
An example of a needy module is a buzzer with a red button. If the buzzer goes off, the defuser has to press the button within 5 seconds
|
||||
or a strike is generated. Needy modules can also have the expert look something up in the manual (if you do this, make sure
|
||||
to balance the time needed by the defuser against the time between the signal that action is needed and the strike).
|
||||
|
||||
Finally, there are also info modules. These don't serve a purpose on their own, they are only useful in combination with
|
||||
puzzle or needy modules. They provide extra information to those modules. These modules were added to the game
|
||||
to make it possible to make puzzle/needy modules with less hardware: puzzle modules generally consist of two "parts":
|
||||
a part that shows information to the defuser that needs to be communicated to the expert and a part that the defuser
|
||||
can interact with to solve the module. With info modules, this first part can be moved to a dedicated module that can
|
||||
be shared between multiple puzzle modules.
|
||||
|
||||
An example of an info module is an LCD display that displays a serial number. There can then be a puzzle module with
|
||||
just two buttons on it. When the defuser is solving that module, the expert reads in the manual "press the second button
|
||||
if the last digit of the serial number is even, otherwise press the first". The expert then asks for the serial number
|
||||
and after that has the defuser press the correct button, solving the puzzle module.
|
||||
|
||||
### Hardware
|
||||
|
||||
In our OBUS implementation, every module has its own microcontroller and CAN module. CAN is a hardware protocol
|
||||
that allows the modules to communicate with the controller (and each other). To write your own module, you don't
|
||||
have to know how CAN works, this is all abstracted away with the OBUS framework. The only thing you need to do
|
||||
is to set the type (puzzle/needy/info) of the module and it's ID. The combination type/ID needs to be unique across
|
||||
the OBUS game, so in order to avoid collisions, you can register your module in TODO LINK MOANA and get an ID.
|
||||
|
||||
In addition to a CAN module, every module also has an RGB LED. This LED is used to show both the
|
||||
state of the module and to indicate if the module has an error.
|
||||
If the module is solved, the LED is green, if a module generates a strike, the module blinks red. There are also several blinking
|
||||
patterns for errors. In order to save pins on the microcontroller for implementing the puzzle, only the red and green
|
||||
parts of the RGB led are connected. You CANNOT use the RGB LED for the puzzle itself: this would be confusing for the player
|
||||
and when debugging a game.
|
||||
|
||||
### A sample game
|
||||
|
||||
This is a description of a sample game with only one module: the `puzzle_testmodule_buttons`. When reading this part, it's useful to have the `puzzle_testmodule_buttons.ino` file next to you as well.
|
||||
|
||||
We'll start this story from the start: the puzzle module boots up.
|
||||
It calls the `obus_module::setup` function to register it's module type and ID. It then keeps calling the `obus_module::loopPuzzle` in a loop.
|
||||
It's important that the `loopPuzzle` function is executed very frequently without delays: if this doesn't happen enough, important CAN messages can get dropped.
|
||||
|
||||
Then after a while, a button gets pressed on the controller and the controller starts preparing to start the game. It first asks all info modules to broadcast their information. After some time, it then asks all puzzle/needy module to register themselves. The controller then confirms that that module will be active in the next round. After some time, the controller broadcasts that the game has started and starts counting down.
|
||||
|
||||
This broadcasts is received on the puzzle module and results in the `callback_game_start` function getting called the next time the
|
||||
`obus::loopPuzzle` is called. The `callback_game_start` function is responsible for setting up the module for a new game. Here, we
|
||||
randomly turn the blue LED on or off, and enable the main loop to start checking button presses.
|
||||
|
||||
After the `callback_game_start` function returns, the microcontroller stays inside the `loop` function, and keeps executing the `obus_module::loopPuzzle`
|
||||
frequently. If the correct button is pressed, it calls the `obus_module::solve` function and turns off input checking. Turning off imput checking is
|
||||
important: that way it's impossible for the puzzle module to generate strikes after it has been solved. If an incorrect button is pressed, it calls the
|
||||
`obus_module::strike` function. That function will send a strike to the controller.
|
||||
|
||||
When `obus_module::solve` is called, the module sends an "I'm solved" CAN packet to the controller. The controller then sees that all modules have been solved,
|
||||
and broadcasts a "solved" packet to every module. The next time the `obus_module::loopPuzzle` function gets called, the
|
||||
`callback_game_stop` will be called. This function is responsible for tearing down the puzzle state. This should have the
|
||||
same effect as just resetting the microcontroller, so if your state is too hard to clean up, you can just reboot the microcontroller.
|
||||
|
||||
## What you need to implement for your own puzzle module
|
||||
|
||||
- The setup code, initializing your microcontroller and setting the type and id of the module with `obus_module::setup`
|
||||
- The main loop code. This should call the `loopPuzzle` function frequently so that all CAN packets can be handled.
|
||||
If you are using calls to `delay()`, try to replace them with a timer (a variable that keeps track of when something should happen). That way the loop can continue executing, without being stuck in the `delay()` function.
|
||||
- A call to the `obus_module::solve` function
|
||||
- A description for the expert of how to defuse the module in `doc/index.md` of your module folder
|
||||
- The `callback_game_start`, `callback_game_stop` and `callback_info` functions. These can be empty.
|
||||
|
||||
## More advanced puzzle modules
|
||||
|
||||
### Receiving game updates
|
||||
|
||||
It's possible to use the current state of the game in your module: the amount of
|
||||
strikes (in microseconds), amount of allowed strikes and time left regularly get
|
||||
broadcast to all modules. That way, you can spice up your puzzle, for example by
|
||||
making the defuser press a button when the timer has a `1` in it, or by
|
||||
having the instructions in the manual vary based on the amount of strikes.
|
||||
|
||||
TODO how will we do this?
|
||||
|
||||
### Using info modules in your puzzle/needy modules
|
||||
|
||||
Using info modules is a great way to reduce the amount of hardware components needed in a puzzle:
|
||||
you can then still have puzzles that change every game, without having to add components that show information
|
||||
to the defuser. Info modules broadcast their information to all modules in the phase before the game starts.
|
||||
Every module can listen to these info messages with the `callback_info` callback. This callback will get
|
||||
the ID of the info module and 7 bytes, as specified by the specific module. The `callback_info` function is
|
||||
responsible for filtering out the info messages the module is interested in, and saving that info for the upcoming game.
|
||||
|
||||
For example, the serial number module has ID 1 and sends in its message 7 random character, chosen randomly from numbers
|
||||
and the uppercase letters.
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 301 KiB After Width: | Height: | Size: 293 KiB |
|
@ -38,8 +38,10 @@ Types for controller:
|
|||
|
||||
- 0 acknowledge valid message
|
||||
[ X B B B B B B B ]
|
||||
--------------
|
||||
reserved
|
||||
- - ----------
|
||||
| ↓ reserved
|
||||
↓ module ID
|
||||
type
|
||||
|
||||
- 1 hello
|
||||
[ X B B B B B B B ]
|
||||
|
@ -49,25 +51,25 @@ Types for controller:
|
|||
- 2 game start
|
||||
[ X B B B B B B B ]
|
||||
-------- - - -
|
||||
time left ↓ ↓ reserved
|
||||
time left ↓ ↓ #puzzle modules
|
||||
#strikes #max strikes
|
||||
|
||||
- 3 state (every x ms – e.g. in the middle of each second)
|
||||
[ X B B B B B B B ]
|
||||
-------- - - -
|
||||
time left ↓ ↓ reserved
|
||||
time left ↓ ↓ #solved puzzle modules
|
||||
#strikes #max strikes
|
||||
|
||||
- 4-6 solved, timeout, strikeout
|
||||
[ X B B B B B B B ]
|
||||
-------- - - -
|
||||
end time ↓ ↓ reserved
|
||||
end time ↓ ↓ #solved puzzle modules
|
||||
#strikes #max strikes
|
||||
|
||||
- 7 info start
|
||||
- 7 info start
|
||||
[ X B B B B B B B ]
|
||||
--------------
|
||||
reserved
|
||||
reserved
|
||||
|
||||
- 8-255 reserved
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ uint8_t payload_type(uint8_t module_type, uint8_t module_id, uint8_t msg_type) {
|
|||
if (module_type == OBUS_TYPE_CONTROLLER && module_id == OBUS_CONTROLLER_ID) {
|
||||
switch (msg_type) {
|
||||
case OBUS_MSGTYPE_C_ACK:
|
||||
return OBUS_PAYLDTYPE_MODULEADDR;
|
||||
case OBUS_MSGTYPE_C_HELLO:
|
||||
return OBUS_PAYLDTYPE_EMPTY;
|
||||
|
||||
|
@ -113,13 +114,14 @@ bool receive(struct message *msg) {
|
|||
break;
|
||||
|
||||
case OBUS_PAYLDTYPE_GAMESTATUS:
|
||||
if (receive_frame.can_dlc < 7) {
|
||||
Serial.println(F("W Received illegal gamestatus msg: payload <7"));
|
||||
if (receive_frame.can_dlc < 8) {
|
||||
Serial.println(F("W Received illegal gamestatus msg: payload <8"));
|
||||
return false;
|
||||
}
|
||||
msg->gamestatus.time_left = unpack_4b_into_u32(&(receive_frame.data[1]));
|
||||
msg->gamestatus.strikes = receive_frame.data[5];
|
||||
msg->gamestatus.max_strikes = receive_frame.data[6];
|
||||
msg->gamestatus.time_left = unpack_4b_into_u32(&(receive_frame.data[1]));
|
||||
msg->gamestatus.strikes = receive_frame.data[5];
|
||||
msg->gamestatus.max_strikes = receive_frame.data[6];
|
||||
msg->gamestatus.puzzle_modules_solved = receive_frame.data[7];
|
||||
break;
|
||||
|
||||
case OBUS_PAYLDTYPE_COUNT:
|
||||
|
@ -137,6 +139,16 @@ bool receive(struct message *msg) {
|
|||
msg->infomessage.len = data_len;
|
||||
}
|
||||
break;
|
||||
case OBUS_PAYLDTYPE_MODULEADDR:
|
||||
{
|
||||
if (receive_frame.can_dlc < 3) {
|
||||
Serial.println(F("W Received illegal count msg: payload <3"));
|
||||
return false;
|
||||
}
|
||||
msg->payload_address.type = receive_frame.data[1];
|
||||
msg->payload_address.id = receive_frame.data[2];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Serial.println(F("W Couldn't determine payload type"));
|
||||
return false;
|
||||
|
@ -175,7 +187,8 @@ void send(struct message *msg) {
|
|||
pack_u32_into_4b(&(send_frame.data[1]), msg->gamestatus.time_left);
|
||||
send_frame.data[5] = msg->gamestatus.strikes;
|
||||
send_frame.data[6] = msg->gamestatus.max_strikes;
|
||||
length = 7;
|
||||
send_frame.data[7] = msg->gamestatus.puzzle_modules_solved;
|
||||
length = 8;
|
||||
break;
|
||||
|
||||
case OBUS_PAYLDTYPE_COUNT:
|
||||
|
@ -188,6 +201,11 @@ void send(struct message *msg) {
|
|||
length = msg->infomessage.len + 1;
|
||||
break;
|
||||
|
||||
case OBUS_PAYLDTYPE_MODULEADDR:
|
||||
send_frame.data[1] = msg->payload_address.type;
|
||||
send_frame.data[2] = msg->payload_address.id;
|
||||
break;
|
||||
|
||||
default:
|
||||
Serial.print(F("E Unknown payload type "));
|
||||
Serial.println(pyld_type);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#define OBUS_PAYLDTYPE_GAMESTATUS 1
|
||||
#define OBUS_PAYLDTYPE_COUNT 2
|
||||
#define OBUS_PAYLDTYPE_INFO 3
|
||||
#define OBUS_PAYLDTYPE_MODULEADDR 4
|
||||
|
||||
#define OBUS_PAYLD_INFO_MAXLEN (OBUS_MSG_LENGTH - 1)
|
||||
|
||||
|
@ -50,6 +51,7 @@ struct payld_gamestatus {
|
|||
uint32_t time_left;
|
||||
uint8_t strikes;
|
||||
uint8_t max_strikes;
|
||||
uint8_t puzzle_modules_solved;
|
||||
};
|
||||
struct payld_infomessage {
|
||||
uint8_t len;
|
||||
|
@ -66,6 +68,7 @@ struct message {
|
|||
struct payld_gamestatus gamestatus;
|
||||
uint8_t count;
|
||||
struct payld_infomessage infomessage;
|
||||
struct module payload_address;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -126,12 +129,13 @@ inline struct message _msg(struct module from, bool priority, uint8_t msg_type)
|
|||
*/
|
||||
inline void _send_payld_gamestatus(
|
||||
struct module from, bool priority, uint8_t msg_type,
|
||||
uint32_t time_left, uint8_t strikes, uint8_t max_strikes) {
|
||||
uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) {
|
||||
|
||||
struct message msg = _msg(from, priority, msg_type);
|
||||
msg.gamestatus.time_left = time_left;
|
||||
msg.gamestatus.strikes = strikes;
|
||||
msg.gamestatus.max_strikes = max_strikes;
|
||||
msg.gamestatus.puzzle_modules_solved = puzzle_modules_solved;
|
||||
send(&msg);
|
||||
}
|
||||
|
||||
|
@ -140,9 +144,10 @@ inline void _send_payld_gamestatus(
|
|||
/**
|
||||
* Send a controller "ACK" OBUS message
|
||||
*/
|
||||
inline void send_c_ack(struct module from) {
|
||||
inline void send_c_ack(struct module from, struct module payload_address) {
|
||||
assert(from.type == OBUS_TYPE_CONTROLLER);
|
||||
struct message msg = _msg(from, false, OBUS_MSGTYPE_C_ACK);
|
||||
msg.payload_address = payload_address;
|
||||
send(&msg);
|
||||
}
|
||||
|
||||
|
@ -160,44 +165,44 @@ inline void send_c_hello(struct module from) {
|
|||
* Send a controller "game start" OBUS message
|
||||
*/
|
||||
inline void send_c_gamestart(
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) {
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) {
|
||||
|
||||
assert(from.type == OBUS_TYPE_CONTROLLER);
|
||||
_send_payld_gamestatus(
|
||||
from, false, OBUS_MSGTYPE_C_GAMESTART, time_left, strikes, max_strikes);
|
||||
from, false, OBUS_MSGTYPE_C_GAMESTART, time_left, strikes, max_strikes, puzzle_modules_solved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a controller "state" OBUS message
|
||||
*/
|
||||
inline void send_c_state(
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) {
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) {
|
||||
|
||||
assert(from.type == OBUS_TYPE_CONTROLLER);
|
||||
_send_payld_gamestatus(
|
||||
from, false, OBUS_MSGTYPE_C_STATE, time_left, strikes, max_strikes);
|
||||
from, false, OBUS_MSGTYPE_C_STATE, time_left, strikes, max_strikes, puzzle_modules_solved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a controller "solved" OBUS message
|
||||
*/
|
||||
inline void send_c_solved(
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) {
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) {
|
||||
|
||||
assert(from.type == OBUS_TYPE_CONTROLLER);
|
||||
_send_payld_gamestatus(
|
||||
from, false, OBUS_MSGTYPE_C_SOLVED, time_left, strikes, max_strikes);
|
||||
from, false, OBUS_MSGTYPE_C_SOLVED, time_left, strikes, max_strikes, puzzle_modules_solved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a controller "timeout" OBUS message
|
||||
*/
|
||||
inline void send_c_timeout(
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) {
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) {
|
||||
|
||||
assert(from.type == OBUS_TYPE_CONTROLLER);
|
||||
_send_payld_gamestatus(
|
||||
from, false, OBUS_MSGTYPE_C_TIMEOUT, time_left, strikes, max_strikes);
|
||||
from, false, OBUS_MSGTYPE_C_TIMEOUT, time_left, strikes, max_strikes, puzzle_modules_solved);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,11 +218,11 @@ inline void send_c_infostart(struct module from) {
|
|||
* Send a controller "strikeout" OBUS message
|
||||
*/
|
||||
inline void send_c_strikeout(
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) {
|
||||
struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) {
|
||||
|
||||
assert(from.type == OBUS_TYPE_CONTROLLER);
|
||||
_send_payld_gamestatus(
|
||||
from, false, OBUS_MSGTYPE_C_STRIKEOUT, time_left, strikes, max_strikes);
|
||||
from, false, OBUS_MSGTYPE_C_STRIKEOUT, time_left, strikes, max_strikes, puzzle_modules_solved);
|
||||
}
|
||||
|
||||
|
||||
|
@ -267,6 +272,10 @@ inline void send_i_infomessage(struct module from, uint8_t *data, uint8_t data_l
|
|||
send(&msg);
|
||||
}
|
||||
|
||||
inline bool is_from_controller(struct module from) {
|
||||
return from.type == OBUS_TYPE_CONTROLLER && from.id == OBUS_CONTROLLER_ID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* end of include guard: OBUS_CAN_H */
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#include "obus_can.h"
|
||||
#include "obus_module.h"
|
||||
|
||||
#define RED_LED A4
|
||||
#define GREEN_LED A5
|
||||
#define RED_LED 4
|
||||
#define GREEN_LED 7
|
||||
|
||||
#define BLINK_DELAY_SLOW 1000
|
||||
#define BLINK_DELAY_FAST 300
|
||||
|
||||
#define MAX_TIME_BETWEEN_CALLS 100
|
||||
|
||||
// Not used normally
|
||||
#define MCP_INT 2
|
||||
|
||||
#define COLOR_OFF ((struct color) {false, false})
|
||||
|
@ -19,6 +22,7 @@ namespace obus_module {
|
|||
struct obus_can::module this_module;
|
||||
uint8_t strike_count;
|
||||
bool active;
|
||||
uint32_t next_loop_call_deadline;
|
||||
|
||||
// Current LED status
|
||||
struct color { bool red; bool green; };
|
||||
|
@ -79,6 +83,7 @@ void _setLedBlink(struct color color, uint16_t delay) {
|
|||
void _resetState() {
|
||||
strike_count = 0;
|
||||
active = false;
|
||||
next_loop_call_deadline = 0;
|
||||
|
||||
if (this_module.type == OBUS_TYPE_PUZZLE || this_module.type == OBUS_TYPE_NEEDY) {
|
||||
pinMode(RED_LED, OUTPUT);
|
||||
|
@ -97,29 +102,55 @@ void setup(uint8_t type, uint8_t id) {
|
|||
_resetState();
|
||||
}
|
||||
|
||||
bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)()) {
|
||||
void empty_callback_info(uint8_t info_id, uint8_t infomessage[7]) {
|
||||
// Mark arguments as not used
|
||||
(void)info_id;
|
||||
(void)infomessage;
|
||||
}
|
||||
|
||||
void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) {
|
||||
// Mark arguments as not used
|
||||
(void)time_left;
|
||||
(void)strikes;
|
||||
(void)max_strikes;
|
||||
(void)puzzle_modules_solved;
|
||||
}
|
||||
|
||||
void blink_error(String message) {
|
||||
bool blink = false;
|
||||
while (true) {
|
||||
digitalWrite(RED_LED, blink);
|
||||
digitalWrite(GREEN_LED, blink);
|
||||
blink = !blink;
|
||||
delay(blink ? BLINK_DELAY_SLOW : BLINK_DELAY_FAST);
|
||||
Serial.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) {
|
||||
// TODO this can be more efficient by only enabling error interrupts and
|
||||
// reacting to the interrupt instead of checking if the flag is set in a loop
|
||||
// We will need to fork our CAN library for this, because the needed functions
|
||||
// are private
|
||||
// We will need to fork our CAN library for this, because the needed functions are private.
|
||||
// Also, we can't do this by default, because the INT pin is normally not connected to the board
|
||||
if (obus_can::is_error_condition()) {
|
||||
bool blink = false;
|
||||
while (true) {
|
||||
digitalWrite(RED_LED, blink);
|
||||
digitalWrite(GREEN_LED, blink);
|
||||
delay(blink ? BLINK_DELAY_SLOW : BLINK_DELAY_FAST);
|
||||
blink = !blink;
|
||||
}
|
||||
blink_error(F("E CAN error"));
|
||||
}
|
||||
|
||||
bool interesting_message = false;
|
||||
if (next_loop_call_deadline != 0 && millis() > next_loop_call_deadline) {
|
||||
blink_error(F("E missed deadline"));
|
||||
}
|
||||
next_loop_call_deadline = millis() + MAX_TIME_BETWEEN_CALLS;
|
||||
|
||||
bool received_message = false;
|
||||
if (obus_can::receive(message)) {
|
||||
if (message->from.type == OBUS_TYPE_CONTROLLER && message->from.id == 0) {
|
||||
received_message = true;
|
||||
if (is_from_controller(message->from)) {
|
||||
switch (message->msg_type) {
|
||||
case OBUS_MSGTYPE_C_GAMESTART:
|
||||
active = true;
|
||||
_setLed(COLOR_YELLOW);
|
||||
callback_game_start();
|
||||
// The field is named puzzle_modules_solved, but it actually contains the amount of puzzle modules
|
||||
callback_game_start(message->gamestatus.puzzle_modules_solved);
|
||||
break;
|
||||
case OBUS_MSGTYPE_C_HELLO:
|
||||
_resetState();
|
||||
|
@ -135,28 +166,32 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void
|
|||
case OBUS_MSGTYPE_C_ACK:
|
||||
break;
|
||||
case OBUS_MSGTYPE_C_STATE:
|
||||
interesting_message = true;
|
||||
callback_state(message->gamestatus.time_left, message->gamestatus.strikes, message->gamestatus.max_strikes, message->gamestatus.puzzle_modules_solved);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (message->from.type == OBUS_TYPE_INFO) {
|
||||
uint8_t infobuffer[7] = {0};
|
||||
memcpy(infobuffer, message->infomessage.data, message->infomessage.len);
|
||||
callback_info(message->from.id, infobuffer);
|
||||
}
|
||||
}
|
||||
|
||||
_ledLoop();
|
||||
|
||||
return interesting_message;
|
||||
return received_message;
|
||||
}
|
||||
|
||||
bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)()) {
|
||||
bool loopNeedy(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) {
|
||||
// For now this is the same function
|
||||
return loopPuzzle(message, callback_game_start, callback_game_stop);
|
||||
return loopPuzzle(message, callback_game_start, callback_game_stop, callback_info, callback_state);
|
||||
}
|
||||
|
||||
bool loopInfo(obus_can::message* message, int (*info_generator)(uint8_t*)) {
|
||||
bool interesting_message = false;
|
||||
if (obus_can::receive(message)) {
|
||||
if (message->from.type == OBUS_TYPE_CONTROLLER && message->from.id == 0) {
|
||||
if (is_from_controller(message->from)) {
|
||||
switch (message->msg_type) {
|
||||
case OBUS_MSGTYPE_C_INFOSTART:
|
||||
{
|
||||
|
|
|
@ -12,9 +12,12 @@ namespace obus_module {
|
|||
|
||||
void setup(uint8_t type, uint8_t id);
|
||||
|
||||
bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)());
|
||||
void empty_callback_info(uint8_t info_id, uint8_t infomessage[7]);
|
||||
void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved);
|
||||
|
||||
bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)());
|
||||
bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state);
|
||||
|
||||
bool loopNeedy(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state);
|
||||
|
||||
bool loopInfo(obus_can::message* message, int (*info_generator)(uint8_t*));
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ uint8_t shiftInFixed(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
|
|||
else
|
||||
value |= digitalRead(dataPin) << (7 - i);
|
||||
digitalWrite(clockPin, HIGH);
|
||||
delay(1);
|
||||
delayMicroseconds(3);
|
||||
digitalWrite(clockPin, LOW);
|
||||
}
|
||||
return value;
|
||||
|
@ -50,7 +50,7 @@ void loop() // run over and over
|
|||
{
|
||||
// read data in
|
||||
digitalWrite(READ_PIN, HIGH);
|
||||
delay(200);
|
||||
delayMicroseconds(3);
|
||||
digitalWrite(READ_PIN, LOW);
|
||||
|
||||
// shift data bit by bit
|
||||
|
|
41
pcb/README.md
Normal file
41
pcb/README.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# OBUS PCB
|
||||
|
||||
![The panelized OBUS PCB](./pcb_kicad.png)
|
||||
|
||||
In order to make it easier for our members to get started creating their own OBUS module,
|
||||
we designed and ordered PCBs they can use instead of having to wire up the basics
|
||||
on a breadboard. The PCB accomodates an Arduino Nano V3 (and clones), an MCP2515 CAN-bus module
|
||||
and an RGB LED. The LED and CAN bus module are connected to pins on the
|
||||
Arduino Nano. All pins on the Arduino Nano are connected to the ajacent pin socket so
|
||||
they can easily be accessed when breadboarding.
|
||||
The pins already used by the OBUS framework are marked with exclamation marks. This does
|
||||
not mean they can't be used for other purposes anymore, just that you need to pay
|
||||
attention when using them: for example the SPI pins can be used for other devices, but
|
||||
the LED pins can't. While picking the pins, we made sure to use the least useful pins
|
||||
for the OBUS framework: we tried to pick as few PWM pins as possible, didn't pick any I2C
|
||||
pins, ...
|
||||
|
||||
## Connecting the parts on the socket.
|
||||
|
||||
We tried our best to make the board as self-explanatory as possible. When pushing the
|
||||
Arduino into its socket, make sure it's in the correct orientation. When connecting the
|
||||
CAN bus module, you'll need to flip it on its back, then look at the silk screen on both
|
||||
the OBUS PCB and the CAN module so that the INT pin is connected in the INT socket hole.
|
||||
|
||||
By default, the INT pin on the CAN module is not connected to the Arduino in order to
|
||||
save pins. If you want to connect the INT pin to pin D2 on the Arduino, you can bridge
|
||||
the jumper on the top right of the board with some solder.
|
||||
|
||||
## Getting this board manufactured
|
||||
|
||||
I order to get this board manufactured cheaper, we panelized it (by putting two OBUS PCBs per ordered "board"). If you want to manufacture this board, there's a file `panel/can_arduino_mini_pcb_panel/fabricate/handin.zip` containing all the
|
||||
Gerber files needed for production. If you modify the original PCB, you can generate
|
||||
the panel with `panel/build.sh`, then use KiCAD to plot the Gerber files.
|
||||
|
||||
### Component list per board
|
||||
|
||||
- 2 1x15 2.54mm pin sockets, we recommend 4 sockets so you can socket the Arduino as well
|
||||
- 1 1x07 2.54mm pin socket
|
||||
- 1 1x02 2.54mm pin socket
|
||||
- 1 common cathode 5mm RGB LED, pin order RCGB
|
||||
- 2 330 ohm through hole resistors
|
28
pcb/can_arduino_mini_pcb/.gitignore
vendored
Normal file
28
pcb/can_arduino_mini_pcb/.gitignore
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
# For PCBs designed using KiCad: http://www.kicad-pcb.org/
|
||||
# Format documentation: http://kicad-pcb.org/help/file-formats/
|
||||
|
||||
# Temporary files
|
||||
*.000
|
||||
*.bak
|
||||
*.bck
|
||||
*.kicad_pcb-bak
|
||||
*.kicad_sch-bak
|
||||
*.kicad_prl
|
||||
*.sch-bak
|
||||
*~
|
||||
_autosave-*
|
||||
*.tmp
|
||||
*-save.pro
|
||||
*-save.kicad_pcb
|
||||
fp-info-cache
|
||||
|
||||
# Netlist files (exported from Eeschema)
|
||||
*.net
|
||||
|
||||
# Autorouter files (exported from Pcbnew)
|
||||
*.dsn
|
||||
*.ses
|
||||
|
||||
# Exported BOM files
|
||||
*.xml
|
||||
*.csv
|
331
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb-cache.lib
Normal file
331
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb-cache.lib
Normal file
|
@ -0,0 +1,331 @@
|
|||
EESchema-LIBRARY Version 2.4
|
||||
#encoding utf-8
|
||||
#
|
||||
# Connector_Conn_01x02_Female
|
||||
#
|
||||
DEF Connector_Conn_01x02_Female J 0 40 Y N 1 F N
|
||||
F0 "J" 0 100 50 H V C CNN
|
||||
F1 "Connector_Conn_01x02_Female" 0 -200 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
A 0 -100 20 901 -901 1 1 6 N 0 -80 0 -120
|
||||
A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
|
||||
P 2 1 1 6 -50 -100 -20 -100 N
|
||||
P 2 1 1 6 -50 0 -20 0 N
|
||||
X Pin_1 1 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_2 2 -200 -100 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Conn_01x07_Female
|
||||
#
|
||||
DEF Connector_Conn_01x07_Female J 0 40 Y N 1 F N
|
||||
F0 "J" 0 400 50 H V C CNN
|
||||
F1 "Connector_Conn_01x07_Female" 0 -400 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
A 0 -300 20 901 -901 1 1 6 N 0 -280 0 -320
|
||||
A 0 -200 20 901 -901 1 1 6 N 0 -180 0 -220
|
||||
A 0 -100 20 901 -901 1 1 6 N 0 -80 0 -120
|
||||
A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
|
||||
A 0 100 20 901 -901 1 1 6 N 0 120 0 80
|
||||
A 0 200 20 901 -901 1 1 6 N 0 220 0 180
|
||||
A 0 300 20 901 -901 1 1 6 N 0 320 0 280
|
||||
P 2 1 1 6 -50 -300 -20 -300 N
|
||||
P 2 1 1 6 -50 -200 -20 -200 N
|
||||
P 2 1 1 6 -50 -100 -20 -100 N
|
||||
P 2 1 1 6 -50 0 -20 0 N
|
||||
P 2 1 1 6 -50 100 -20 100 N
|
||||
P 2 1 1 6 -50 200 -20 200 N
|
||||
P 2 1 1 6 -50 300 -20 300 N
|
||||
X Pin_1 1 -200 300 150 R 50 50 1 1 P
|
||||
X Pin_2 2 -200 200 150 R 50 50 1 1 P
|
||||
X Pin_3 3 -200 100 150 R 50 50 1 1 P
|
||||
X Pin_4 4 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_5 5 -200 -100 150 R 50 50 1 1 P
|
||||
X Pin_6 6 -200 -200 150 R 50 50 1 1 P
|
||||
X Pin_7 7 -200 -300 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Conn_01x15_Female
|
||||
#
|
||||
DEF Connector_Conn_01x15_Female J 0 40 Y N 1 F N
|
||||
F0 "J" 0 800 50 H V C CNN
|
||||
F1 "Connector_Conn_01x15_Female" 0 -800 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
A 0 -700 20 901 -901 1 1 6 N 0 -680 0 -720
|
||||
A 0 -600 20 901 -901 1 1 6 N 0 -580 0 -620
|
||||
A 0 -500 20 901 -901 1 1 6 N 0 -480 0 -520
|
||||
A 0 -400 20 901 -901 1 1 6 N 0 -380 0 -420
|
||||
A 0 -300 20 901 -901 1 1 6 N 0 -280 0 -320
|
||||
A 0 -200 20 901 -901 1 1 6 N 0 -180 0 -220
|
||||
A 0 -100 20 901 -901 1 1 6 N 0 -80 0 -120
|
||||
A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
|
||||
A 0 100 20 901 -901 1 1 6 N 0 120 0 80
|
||||
A 0 200 20 901 -901 1 1 6 N 0 220 0 180
|
||||
A 0 300 20 901 -901 1 1 6 N 0 320 0 280
|
||||
A 0 400 20 901 -901 1 1 6 N 0 420 0 380
|
||||
A 0 500 20 901 -901 1 1 6 N 0 520 0 480
|
||||
A 0 600 20 901 -901 1 1 6 N 0 620 0 580
|
||||
A 0 700 20 901 -901 1 1 6 N 0 720 0 680
|
||||
P 2 1 1 6 -50 -700 -20 -700 N
|
||||
P 2 1 1 6 -50 -600 -20 -600 N
|
||||
P 2 1 1 6 -50 -500 -20 -500 N
|
||||
P 2 1 1 6 -50 -400 -20 -400 N
|
||||
P 2 1 1 6 -50 -300 -20 -300 N
|
||||
P 2 1 1 6 -50 -200 -20 -200 N
|
||||
P 2 1 1 6 -50 -100 -20 -100 N
|
||||
P 2 1 1 6 -50 0 -20 0 N
|
||||
P 2 1 1 6 -50 100 -20 100 N
|
||||
P 2 1 1 6 -50 200 -20 200 N
|
||||
P 2 1 1 6 -50 300 -20 300 N
|
||||
P 2 1 1 6 -50 400 -20 400 N
|
||||
P 2 1 1 6 -50 500 -20 500 N
|
||||
P 2 1 1 6 -50 600 -20 600 N
|
||||
P 2 1 1 6 -50 700 -20 700 N
|
||||
X Pin_1 1 -200 700 150 R 50 50 1 1 P
|
||||
X Pin_10 10 -200 -200 150 R 50 50 1 1 P
|
||||
X Pin_11 11 -200 -300 150 R 50 50 1 1 P
|
||||
X Pin_12 12 -200 -400 150 R 50 50 1 1 P
|
||||
X Pin_13 13 -200 -500 150 R 50 50 1 1 P
|
||||
X Pin_14 14 -200 -600 150 R 50 50 1 1 P
|
||||
X Pin_15 15 -200 -700 150 R 50 50 1 1 P
|
||||
X Pin_2 2 -200 600 150 R 50 50 1 1 P
|
||||
X Pin_3 3 -200 500 150 R 50 50 1 1 P
|
||||
X Pin_4 4 -200 400 150 R 50 50 1 1 P
|
||||
X Pin_5 5 -200 300 150 R 50 50 1 1 P
|
||||
X Pin_6 6 -200 200 150 R 50 50 1 1 P
|
||||
X Pin_7 7 -200 100 150 R 50 50 1 1 P
|
||||
X Pin_8 8 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_9 9 -200 -100 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_Jumper_NO_Small
|
||||
#
|
||||
DEF Device_Jumper_NO_Small JP 0 30 N N 1 F N
|
||||
F0 "JP" 0 80 50 H V C CNN
|
||||
F1 "Device_Jumper_NO_Small" 10 -60 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
SolderJumper*Open*
|
||||
Jumper*
|
||||
TestPoint*2Pads*
|
||||
TestPoint*Bridge*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
C -40 0 20 0 1 0 N
|
||||
C 40 0 20 0 1 0 N
|
||||
X 1 1 -100 0 40 R 50 50 0 1 P
|
||||
X 2 2 100 0 40 L 50 50 0 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_LED_RCGB
|
||||
#
|
||||
DEF Device_LED_RCGB D 0 0 Y N 1 F N
|
||||
F0 "D" 0 370 50 H V C CNN
|
||||
F1 "Device_LED_RCGB" 0 -350 50 H V C CNN
|
||||
F2 "" 0 -50 50 H I C CNN
|
||||
F3 "" 0 -50 50 H I C CNN
|
||||
$FPLIST
|
||||
LED*
|
||||
LED_SMD:*
|
||||
LED_THT:*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
C -80 0 10 0 1 0 F
|
||||
T 0 75 -250 50 0 0 0 B Normal 0 C C
|
||||
T 0 75 -50 50 0 0 0 G Normal 0 C C
|
||||
T 0 75 150 50 0 0 0 R Normal 0 C C
|
||||
S 50 -50 50 50 0 1 0 N
|
||||
S 50 50 50 50 0 1 0 N
|
||||
S 50 150 50 250 0 1 0 N
|
||||
S 50 250 50 250 0 1 0 N
|
||||
S 110 330 -110 -300 0 1 10 f
|
||||
P 2 0 1 0 -50 -200 50 -200 N
|
||||
P 2 0 1 10 -50 -150 -50 -250 N
|
||||
P 2 0 1 0 -50 0 -100 0 N
|
||||
P 2 0 1 10 -50 50 -50 -50 N
|
||||
P 2 0 1 0 -50 200 50 200 N
|
||||
P 2 0 1 10 -50 250 -50 150 N
|
||||
P 2 0 1 0 50 -200 100 -200 N
|
||||
P 2 0 1 0 50 0 -50 0 N
|
||||
P 2 0 1 0 50 0 100 0 N
|
||||
P 2 0 1 0 50 200 100 200 N
|
||||
P 3 0 1 0 -50 50 -50 -50 -50 -50 N
|
||||
P 3 0 1 0 -50 250 -50 150 -50 150 N
|
||||
P 4 0 1 0 -50 200 -80 200 -80 -200 -40 -200 N
|
||||
P 4 0 1 10 50 -150 50 -250 -50 -200 50 -150 N
|
||||
P 4 0 1 10 50 50 50 -50 -50 0 50 50 N
|
||||
P 4 0 1 10 50 250 50 150 -50 200 50 250 N
|
||||
P 5 0 1 0 -40 -150 20 -90 -10 -90 20 -90 20 -120 N
|
||||
P 5 0 1 0 -40 50 20 110 -10 110 20 110 20 80 N
|
||||
P 5 0 1 0 -40 250 20 310 -10 310 20 310 20 280 N
|
||||
P 5 0 1 0 0 -150 60 -90 30 -90 60 -90 60 -120 N
|
||||
P 5 0 1 0 0 50 60 110 30 110 60 110 60 80 N
|
||||
P 5 0 1 0 0 250 60 310 30 310 60 310 60 280 N
|
||||
X RA 1 200 200 100 L 50 50 1 1 P
|
||||
X K 2 -200 0 100 R 50 50 1 1 P
|
||||
X GA 3 200 0 100 L 50 50 1 1 P
|
||||
X BA 4 200 -200 100 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_R
|
||||
#
|
||||
DEF Device_R R 0 0 N Y 1 F N
|
||||
F0 "R" 80 0 50 V V C CNN
|
||||
F1 "Device_R" 0 0 50 V V C CNN
|
||||
F2 "" -70 0 50 V I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
R_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -40 -100 40 100 0 1 10 N
|
||||
X ~ 1 0 150 50 D 50 50 1 1 P
|
||||
X ~ 2 0 -150 50 U 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# MCU_Module_Arduino_Nano_v3.x
|
||||
#
|
||||
DEF MCU_Module_Arduino_Nano_v3.x A 0 20 Y Y 1 F N
|
||||
F0 "A" -400 925 50 H V L BNN
|
||||
F1 "MCU_Module_Arduino_Nano_v3.x" 200 -950 50 H V L TNN
|
||||
F2 "Module:Arduino_Nano" 0 0 50 H I C CIN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
ALIAS Arduino_Nano_v3.x
|
||||
$FPLIST
|
||||
Arduino*Nano*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -400 900 400 -900 0 1 10 f
|
||||
X D1/TX 1 -500 500 100 R 50 50 1 1 B
|
||||
X D7 10 -500 -100 100 R 50 50 1 1 B
|
||||
X D8 11 -500 -200 100 R 50 50 1 1 B
|
||||
X D9 12 -500 -300 100 R 50 50 1 1 B
|
||||
X D10 13 -500 -400 100 R 50 50 1 1 B
|
||||
X D11 14 -500 -500 100 R 50 50 1 1 B
|
||||
X D12 15 -500 -600 100 R 50 50 1 1 B
|
||||
X D13 16 -500 -700 100 R 50 50 1 1 B
|
||||
X 3V3 17 100 1000 100 D 50 50 1 1 w
|
||||
X AREF 18 500 200 100 L 50 50 1 1 I
|
||||
X A0 19 500 0 100 L 50 50 1 1 B
|
||||
X D0/RX 2 -500 600 100 R 50 50 1 1 B
|
||||
X A1 20 500 -100 100 L 50 50 1 1 B
|
||||
X A2 21 500 -200 100 L 50 50 1 1 B
|
||||
X A3 22 500 -300 100 L 50 50 1 1 B
|
||||
X A4 23 500 -400 100 L 50 50 1 1 B
|
||||
X A5 24 500 -500 100 L 50 50 1 1 B
|
||||
X A6 25 500 -600 100 L 50 50 1 1 B
|
||||
X A7 26 500 -700 100 L 50 50 1 1 B
|
||||
X +5V 27 200 1000 100 D 50 50 1 1 w
|
||||
X ~RESET 28 500 600 100 L 50 50 1 1 I
|
||||
X GND 29 100 -1000 100 U 50 50 1 1 W
|
||||
X ~RESET 3 500 500 100 L 50 50 1 1 I
|
||||
X VIN 30 -100 1000 100 D 50 50 1 1 W
|
||||
X GND 4 0 -1000 100 U 50 50 1 1 W
|
||||
X D2 5 -500 400 100 R 50 50 1 1 B
|
||||
X D3 6 -500 300 100 R 50 50 1 1 B
|
||||
X D4 7 -500 200 100 R 50 50 1 1 B
|
||||
X D5 8 -500 100 100 R 50 50 1 1 B
|
||||
X D6 9 -500 0 100 R 50 50 1 1 B
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# custom_components_CAN_MODULE
|
||||
#
|
||||
DEF custom_components_CAN_MODULE U 0 40 Y Y 1 F N
|
||||
F0 "U" -250 -400 50 H V C CNN
|
||||
F1 "custom_components_CAN_MODULE" -50 400 50 H V C CNN
|
||||
F2 "" -500 50 50 H I C CNN
|
||||
F3 "" -500 50 50 H I C CNN
|
||||
DRAW
|
||||
P 5 0 1 0 -300 350 -300 -350 200 -350 200 350 -300 350 f
|
||||
X CS ~ -400 -100 100 R 50 50 1 1 I
|
||||
X GND ~ -400 -200 100 R 50 50 1 1 W
|
||||
X INT ~ -400 300 100 R 50 50 1 1 O
|
||||
X SCK ~ -400 200 100 R 50 50 1 1 I
|
||||
X SI ~ -400 100 100 R 50 50 1 1 I
|
||||
X SO ~ -400 0 100 R 50 50 1 1 O
|
||||
X VCC ~ -400 -300 100 R 50 50 1 1 W
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_+3.3V
|
||||
#
|
||||
DEF power_+3.3V #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "power_+3.3V" 0 140 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
ALIAS +3.3V
|
||||
DRAW
|
||||
P 2 0 1 0 -30 50 0 100 N
|
||||
P 2 0 1 0 0 0 0 100 N
|
||||
P 2 0 1 0 0 100 30 50 N
|
||||
X +3V3 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_+5V
|
||||
#
|
||||
DEF power_+5V #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "power_+5V" 0 140 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 2 0 1 0 -30 50 0 100 N
|
||||
P 2 0 1 0 0 0 0 100 N
|
||||
P 2 0 1 0 0 100 30 50 N
|
||||
X +5V 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_GND
|
||||
#
|
||||
DEF power_GND #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -250 50 H I C CNN
|
||||
F1 "power_GND" 0 -150 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
||||
X GND 1 0 0 0 D 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_VCC
|
||||
#
|
||||
DEF power_VCC #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "power_VCC" 0 150 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 2 0 1 0 -30 50 0 100 N
|
||||
P 2 0 1 0 0 0 0 100 N
|
||||
P 2 0 1 0 0 100 30 50 N
|
||||
X VCC 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
1599
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb.kicad_pcb
Normal file
1599
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb.kicad_pcb
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,106 @@
|
|||
(module Zeusbadge:logo_small (layer F.Cu) (tedit 0)
|
||||
(fp_text reference Ref** (at 0 0) (layer F.SilkS) hide
|
||||
(effects (font (size 1.27 1.27) (thickness 0.15)))
|
||||
)
|
||||
(fp_text value Val** (at 0 0) (layer F.SilkS) hide
|
||||
(effects (font (size 1.27 1.27) (thickness 0.15)))
|
||||
)
|
||||
(fp_poly (pts (xy -1.016 -3.288689) (xy -1.142003 -3.138997) (xy -1.268007 -2.989305) (xy -1.182104 -3.030809)
|
||||
(xy -1.025377 -3.087386) (xy -0.846598 -3.120172) (xy -0.657547 -3.129238) (xy -0.470004 -3.114655)
|
||||
(xy -0.295752 -3.076497) (xy -0.164929 -3.024586) (xy -0.067915 -2.961689) (xy 0.032277 -2.874577)
|
||||
(xy 0.12265 -2.776208) (xy 0.190203 -2.679541) (xy 0.200396 -2.660424) (xy 0.254 -2.552855)
|
||||
(xy 0.254 -3.069167) (xy 0.881518 -3.069167) (xy 0.880072 -2.450042) (xy 0.879921 -2.267152)
|
||||
(xy 0.880578 -2.121569) (xy 0.882289 -2.008269) (xy 0.885296 -1.922228) (xy 0.889844 -1.858422)
|
||||
(xy 0.896176 -1.811829) (xy 0.904535 -1.777425) (xy 0.913896 -1.752948) (xy 0.971152 -1.672643)
|
||||
(xy 1.054138 -1.625167) (xy 1.16035 -1.611805) (xy 1.185619 -1.613478) (xy 1.28122 -1.634538)
|
||||
(xy 1.357754 -1.681383) (xy 1.424353 -1.760687) (xy 1.45408 -1.80975) (xy 1.513417 -1.915583)
|
||||
(xy 1.527029 -3.069167) (xy 2.137833 -3.069167) (xy 2.137833 -2.72153) (xy 2.185458 -2.815669)
|
||||
(xy 2.258964 -2.9177) (xy 2.365182 -3.005012) (xy 2.495233 -3.070792) (xy 2.536114 -3.084859)
|
||||
(xy 2.623269 -3.102769) (xy 2.742311 -3.114551) (xy 2.883255 -3.120301) (xy 3.036115 -3.120112)
|
||||
(xy 3.190905 -3.114079) (xy 3.337639 -3.102295) (xy 3.46633 -3.084856) (xy 3.513667 -3.075635)
|
||||
(xy 3.693583 -3.036259) (xy 3.705475 -2.544021) (xy 3.550865 -2.604056) (xy 3.326485 -2.672813)
|
||||
(xy 3.104529 -2.705117) (xy 2.963429 -2.705744) (xy 2.877009 -2.697913) (xy 2.819472 -2.683696)
|
||||
(xy 2.777438 -2.659152) (xy 2.763281 -2.646802) (xy 2.719319 -2.584497) (xy 2.711743 -2.519641)
|
||||
(xy 2.726274 -2.482613) (xy 2.766383 -2.450155) (xy 2.838853 -2.419933) (xy 2.933728 -2.395388)
|
||||
(xy 3.01625 -2.382466) (xy 3.156457 -2.361403) (xy 3.299459 -2.331076) (xy 3.433035 -2.294693)
|
||||
(xy 3.544964 -2.255458) (xy 3.60293 -2.228539) (xy 3.704631 -2.153435) (xy 3.758668 -2.084122)
|
||||
(xy 3.781923 -2.040048) (xy 3.796927 -1.996041) (xy 3.805436 -1.941265) (xy 3.809206 -1.864882)
|
||||
(xy 3.81 -1.767417) (xy 3.809025 -1.662024) (xy 3.804921 -1.588087) (xy 3.795919 -1.534747)
|
||||
(xy 3.780252 -1.491148) (xy 3.758318 -1.450115) (xy 3.674898 -1.349053) (xy 3.556203 -1.268239)
|
||||
(xy 3.404468 -1.208296) (xy 3.221927 -1.169846) (xy 3.010815 -1.153512) (xy 2.773365 -1.159916)
|
||||
(xy 2.729504 -1.163401) (xy 2.612096 -1.17531) (xy 2.49223 -1.190343) (xy 2.386424 -1.206294)
|
||||
(xy 2.329159 -1.21691) (xy 2.254258 -1.23242) (xy 2.19722 -1.243771) (xy 2.169123 -1.248766)
|
||||
(xy 2.168199 -1.248833) (xy 2.164593 -1.268613) (xy 2.16165 -1.322407) (xy 2.159682 -1.401899)
|
||||
(xy 2.159 -1.494515) (xy 2.159483 -1.59945) (xy 2.161637 -1.668627) (xy 2.166519 -1.708619)
|
||||
(xy 2.175187 -1.725996) (xy 2.188698 -1.727331) (xy 2.196042 -1.7247) (xy 2.366911 -1.663036)
|
||||
(xy 2.546916 -1.615359) (xy 2.72448 -1.583779) (xy 2.888025 -1.570405) (xy 3.013854 -1.575702)
|
||||
(xy 3.11662 -1.599827) (xy 3.193226 -1.6406) (xy 3.239488 -1.693512) (xy 3.251217 -1.754055)
|
||||
(xy 3.230422 -1.808898) (xy 3.205257 -1.838257) (xy 3.168347 -1.862212) (xy 3.113195 -1.882828)
|
||||
(xy 3.0333 -1.902173) (xy 2.922163 -1.922312) (xy 2.826401 -1.937369) (xy 2.636219 -1.972919)
|
||||
(xy 2.483188 -2.017374) (xy 2.362634 -2.073083) (xy 2.269885 -2.142399) (xy 2.200269 -2.227675)
|
||||
(xy 2.179975 -2.262724) (xy 2.139704 -2.338917) (xy 2.138769 -1.762125) (xy 2.137833 -1.185333)
|
||||
(xy 1.524 -1.185333) (xy 1.524 -1.453244) (xy 1.425698 -1.359054) (xy 1.292809 -1.254409)
|
||||
(xy 1.150557 -1.18894) (xy 0.99134 -1.159524) (xy 0.93419 -1.157201) (xy 0.761957 -1.169408)
|
||||
(xy 0.618339 -1.21056) (xy 0.500057 -1.281763) (xy 0.460985 -1.317015) (xy 0.386955 -1.405718)
|
||||
(xy 0.332771 -1.507635) (xy 0.294623 -1.632148) (xy 0.268702 -1.788638) (xy 0.268388 -1.791268)
|
||||
(xy 0.2448 -1.989667) (xy -0.41735 -1.989667) (xy -0.608043 -1.989812) (xy -0.760238 -1.989585)
|
||||
(xy -0.877765 -1.987996) (xy -0.964456 -1.984052) (xy -1.024141 -1.976762) (xy -1.060652 -1.965135)
|
||||
(xy -1.077818 -1.948179) (xy -1.079471 -1.924903) (xy -1.069441 -1.894314) (xy -1.051559 -1.855422)
|
||||
(xy -1.039127 -1.828731) (xy -0.969825 -1.719242) (xy -0.873815 -1.640901) (xy -0.763574 -1.594829)
|
||||
(xy -0.629055 -1.573158) (xy -0.471256 -1.577406) (xy -0.299116 -1.606033) (xy -0.121578 -1.657497)
|
||||
(xy 0.05242 -1.73026) (xy 0.068188 -1.738097) (xy 0.132329 -1.769626) (xy 0.180289 -1.791683)
|
||||
(xy 0.20048 -1.799167) (xy 0.204892 -1.779397) (xy 0.208484 -1.725667) (xy 0.210869 -1.646349)
|
||||
(xy 0.211667 -1.556671) (xy 0.211667 -1.314175) (xy 0.04669 -1.262059) (xy -0.054642 -1.232446)
|
||||
(xy -0.162556 -1.204646) (xy -0.253911 -1.184615) (xy -0.254935 -1.184423) (xy -0.349356 -1.171573)
|
||||
(xy -0.466152 -1.162669) (xy -0.592323 -1.15798) (xy -0.714868 -1.157772) (xy -0.820786 -1.162312)
|
||||
(xy -0.894292 -1.17129) (xy -0.973667 -1.187252) (xy -0.973667 -0.592667) (xy -3.788833 -0.592667)
|
||||
(xy -3.788619 -0.851958) (xy -3.788404 -1.11125) (xy -3.691228 -1.227667) (xy -2.753326 -1.227667)
|
||||
(xy -1.942871 -1.227684) (xy -1.132417 -1.2277) (xy -1.222755 -1.272417) (xy -1.367732 -1.366825)
|
||||
(xy -1.492981 -1.493678) (xy -1.592451 -1.645357) (xy -1.660092 -1.814243) (xy -1.663808 -1.827746)
|
||||
(xy -1.678724 -1.912308) (xy -1.688158 -2.024014) (xy -1.691884 -2.148001) (xy -1.689677 -2.269407)
|
||||
(xy -1.68153 -2.370667) (xy -1.076545 -2.370667) (xy -0.300792 -2.370667) (xy -0.318324 -2.448404)
|
||||
(xy -0.36246 -2.557083) (xy -0.437382 -2.63888) (xy -0.538762 -2.690555) (xy -0.662271 -2.708869)
|
||||
(xy -0.66642 -2.708869) (xy -0.798212 -2.690354) (xy -0.91018 -2.638495) (xy -0.99706 -2.556982)
|
||||
(xy -1.053588 -2.449505) (xy -1.058358 -2.434082) (xy -1.076545 -2.370667) (xy -1.68153 -2.370667)
|
||||
(xy -1.681312 -2.37337) (xy -1.672832 -2.422989) (xy -1.661944 -2.476782) (xy -1.658356 -2.509334)
|
||||
(xy -1.659172 -2.512894) (xy -1.673809 -2.4991) (xy -1.711713 -2.457234) (xy -1.769026 -2.391729)
|
||||
(xy -1.841895 -2.307017) (xy -1.926463 -2.207531) (xy -1.980794 -2.143095) (xy -2.08913 -2.014314)
|
||||
(xy -2.205237 -1.876443) (xy -2.320634 -1.739541) (xy -2.426845 -1.613664) (xy -2.515391 -1.508871)
|
||||
(xy -2.524955 -1.497565) (xy -2.753326 -1.227667) (xy -3.691228 -1.227667) (xy -2.940318 -2.12725)
|
||||
(xy -2.092231 -3.14325) (xy -2.929949 -3.148785) (xy -3.767667 -3.154319) (xy -3.767667 -3.788833)
|
||||
(xy -1.016 -3.788833) (xy -1.016 -3.288689)) (layer F.SilkS) (width 0.01))
|
||||
(fp_poly (pts (xy 2.207666 -1.024057) (xy 2.273262 -1.013955) (xy 2.330212 -0.992493) (xy 2.3744 -0.968396)
|
||||
(xy 2.501053 -0.8699) (xy 2.599025 -0.741854) (xy 2.645181 -0.645583) (xy 2.685961 -0.53975)
|
||||
(xy 2.687064 -0.767292) (xy 2.688167 -0.994833) (xy 3.132667 -0.994833) (xy 3.132667 0.423333)
|
||||
(xy 2.688167 0.423333) (xy 2.685961 -0.052917) (xy 2.645181 0.052917) (xy 2.57002 0.196383)
|
||||
(xy 2.468504 0.309449) (xy 2.344269 0.389265) (xy 2.200952 0.432979) (xy 2.152866 0.438782)
|
||||
(xy 2.004569 0.436976) (xy 1.876802 0.403809) (xy 1.758684 0.3363) (xy 1.747103 0.327637)
|
||||
(xy 1.651 0.254279) (xy 1.651 0.9525) (xy 1.185819 0.9525) (xy 1.180284 0.115033)
|
||||
(xy 1.177538 -0.300551) (xy 1.652692 -0.300551) (xy 1.660694 -0.187641) (xy 1.687052 -0.083604)
|
||||
(xy 1.732023 0.00204) (xy 1.780419 0.050112) (xy 1.846255 0.075872) (xy 1.932137 0.083376)
|
||||
(xy 2.019848 0.07247) (xy 2.075026 0.052558) (xy 2.13734 0.006643) (xy 2.179162 -0.059496)
|
||||
(xy 2.203024 -0.152327) (xy 2.211455 -0.278317) (xy 2.211551 -0.296333) (xy 2.204834 -0.426827)
|
||||
(xy 2.182997 -0.52337) (xy 2.14351 -0.59243) (xy 2.08384 -0.640473) (xy 2.075026 -0.645225)
|
||||
(xy 1.989624 -0.671278) (xy 1.892808 -0.674331) (xy 1.806616 -0.653963) (xy 1.799167 -0.650491)
|
||||
(xy 1.736286 -0.597303) (xy 1.690743 -0.514903) (xy 1.662794 -0.412812) (xy 1.652692 -0.300551)
|
||||
(xy 1.177538 -0.300551) (xy 1.17475 -0.722434) (xy 1.026583 -0.154842) (xy 0.878417 0.41275)
|
||||
(xy 0.383355 0.424656) (xy 0.362498 0.349117) (xy 0.350927 0.304331) (xy 0.331668 0.22658)
|
||||
(xy 0.306727 0.124107) (xy 0.278113 0.005155) (xy 0.251575 -0.106244) (xy 0.222709 -0.225502)
|
||||
(xy 0.196674 -0.328414) (xy 0.17514 -0.408754) (xy 0.159774 -0.460292) (xy 0.152249 -0.476805)
|
||||
(xy 0.144668 -0.454408) (xy 0.128693 -0.396995) (xy 0.105929 -0.310689) (xy 0.077979 -0.201608)
|
||||
(xy 0.046449 -0.075875) (xy 0.034452 -0.027397) (xy -0.074083 0.41275) (xy -0.321797 0.418705)
|
||||
(xy -0.569511 0.424659) (xy -0.590367 0.344621) (xy -0.666863 0.050855) (xy -0.732925 -0.203265)
|
||||
(xy -0.788885 -0.419031) (xy -0.835077 -0.59774) (xy -0.871834 -0.740684) (xy -0.899489 -0.849158)
|
||||
(xy -0.918375 -0.924457) (xy -0.928824 -0.967875) (xy -0.931333 -0.980507) (xy -0.91163 -0.9864)
|
||||
(xy -0.85836 -0.991117) (xy -0.780289 -0.99409) (xy -0.710078 -0.994833) (xy -0.488823 -0.994833)
|
||||
(xy -0.470222 -0.926042) (xy -0.459474 -0.88389) (xy -0.440884 -0.808447) (xy -0.41637 -0.707614)
|
||||
(xy -0.387856 -0.589292) (xy -0.358424 -0.466258) (xy -0.265227 -0.075266) (xy -0.167992 -0.476841)
|
||||
(xy -0.136895 -0.605159) (xy -0.108363 -0.722693) (xy -0.08422 -0.821947) (xy -0.066288 -0.895423)
|
||||
(xy -0.056392 -0.935624) (xy -0.056142 -0.936625) (xy -0.041527 -0.994833) (xy 0.352246 -0.994833)
|
||||
(xy 0.45534 -0.560917) (xy 0.486502 -0.432165) (xy 0.515084 -0.318599) (xy 0.539481 -0.226237)
|
||||
(xy 0.558086 -0.161099) (xy 0.569293 -0.129204) (xy 0.571093 -0.127) (xy 0.579524 -0.146617)
|
||||
(xy 0.595904 -0.201456) (xy 0.618624 -0.285499) (xy 0.646075 -0.392728) (xy 0.676647 -0.517126)
|
||||
(xy 0.687146 -0.560917) (xy 0.790538 -0.994834) (xy 1.220769 -0.994833) (xy 1.651 -0.994833)
|
||||
(xy 1.651 -0.846946) (xy 1.747878 -0.920895) (xy 1.817895 -0.970026) (xy 1.881399 -1.001301)
|
||||
(xy 1.951775 -1.018557) (xy 2.042408 -1.02563) (xy 2.116667 -1.026583) (xy 2.207666 -1.024057)) (layer F.SilkS) (width 0.01))
|
||||
)
|
259
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb.pro
Normal file
259
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb.pro
Normal file
|
@ -0,0 +1,259 @@
|
|||
update=Tue 26 Jan 2021 04:50:01 CET
|
||||
version=1
|
||||
last_client=kicad
|
||||
[general]
|
||||
version=1
|
||||
RootSch=
|
||||
BoardNm=
|
||||
[cvpcb]
|
||||
version=1
|
||||
NetIExt=net
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
[eeschema/libraries]
|
||||
[schematic_editor]
|
||||
version=1
|
||||
PageLayoutDescrFile=
|
||||
PlotDirectoryName=
|
||||
SubpartIdSeparator=0
|
||||
SubpartFirstId=65
|
||||
NetFmtName=Pcbnew
|
||||
SpiceAjustPassiveValues=0
|
||||
LabSize=50
|
||||
ERC_TestSimilarLabels=1
|
||||
[pcbnew]
|
||||
version=1
|
||||
PageLayoutDescrFile=
|
||||
LastNetListRead=can_arduino_mini_pcb.net
|
||||
CopperLayerCount=2
|
||||
BoardThickness=1.6
|
||||
AllowMicroVias=0
|
||||
AllowBlindVias=0
|
||||
RequireCourtyardDefinitions=0
|
||||
ProhibitOverlappingCourtyards=1
|
||||
MinTrackWidth=0.2
|
||||
MinViaDiameter=0.4
|
||||
MinViaDrill=0.3
|
||||
MinMicroViaDiameter=0.2
|
||||
MinMicroViaDrill=0.09999999999999999
|
||||
MinHoleToHole=0.25
|
||||
TrackWidth1=0.25
|
||||
ViaDiameter1=0.8
|
||||
ViaDrill1=0.4
|
||||
dPairWidth1=0.2
|
||||
dPairGap1=0.25
|
||||
dPairViaGap1=0.25
|
||||
SilkLineWidth=0.12
|
||||
SilkTextSizeV=1
|
||||
SilkTextSizeH=1
|
||||
SilkTextSizeThickness=0.15
|
||||
SilkTextItalic=0
|
||||
SilkTextUpright=1
|
||||
CopperLineWidth=0.2
|
||||
CopperTextSizeV=1.5
|
||||
CopperTextSizeH=1.5
|
||||
CopperTextThickness=0.3
|
||||
CopperTextItalic=0
|
||||
CopperTextUpright=1
|
||||
EdgeCutLineWidth=0.05
|
||||
CourtyardLineWidth=0.05
|
||||
OthersLineWidth=0.15
|
||||
OthersTextSizeV=1
|
||||
OthersTextSizeH=1
|
||||
OthersTextSizeThickness=0.15
|
||||
OthersTextItalic=0
|
||||
OthersTextUpright=1
|
||||
SolderMaskClearance=0
|
||||
SolderMaskMinWidth=0
|
||||
SolderPasteClearance=0
|
||||
SolderPasteRatio=-0
|
||||
[pcbnew/Layer.F.Cu]
|
||||
Name=F.Cu
|
||||
Type=0
|
||||
Enabled=1
|
||||
[pcbnew/Layer.In1.Cu]
|
||||
Name=In1.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In2.Cu]
|
||||
Name=In2.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In3.Cu]
|
||||
Name=In3.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In4.Cu]
|
||||
Name=In4.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In5.Cu]
|
||||
Name=In5.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In6.Cu]
|
||||
Name=In6.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In7.Cu]
|
||||
Name=In7.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In8.Cu]
|
||||
Name=In8.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In9.Cu]
|
||||
Name=In9.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In10.Cu]
|
||||
Name=In10.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In11.Cu]
|
||||
Name=In11.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In12.Cu]
|
||||
Name=In12.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In13.Cu]
|
||||
Name=In13.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In14.Cu]
|
||||
Name=In14.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In15.Cu]
|
||||
Name=In15.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In16.Cu]
|
||||
Name=In16.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In17.Cu]
|
||||
Name=In17.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In18.Cu]
|
||||
Name=In18.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In19.Cu]
|
||||
Name=In19.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In20.Cu]
|
||||
Name=In20.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In21.Cu]
|
||||
Name=In21.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In22.Cu]
|
||||
Name=In22.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In23.Cu]
|
||||
Name=In23.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In24.Cu]
|
||||
Name=In24.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In25.Cu]
|
||||
Name=In25.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In26.Cu]
|
||||
Name=In26.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In27.Cu]
|
||||
Name=In27.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In28.Cu]
|
||||
Name=In28.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In29.Cu]
|
||||
Name=In29.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.In30.Cu]
|
||||
Name=In30.Cu
|
||||
Type=0
|
||||
Enabled=0
|
||||
[pcbnew/Layer.B.Cu]
|
||||
Name=B.Cu
|
||||
Type=0
|
||||
Enabled=1
|
||||
[pcbnew/Layer.B.Adhes]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.F.Adhes]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.B.Paste]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.F.Paste]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.B.SilkS]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.F.SilkS]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.B.Mask]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.F.Mask]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.Dwgs.User]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.Cmts.User]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.Eco1.User]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.Eco2.User]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.Edge.Cuts]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.Margin]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.B.CrtYd]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.F.CrtYd]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.B.Fab]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.F.Fab]
|
||||
Enabled=1
|
||||
[pcbnew/Layer.Rescue]
|
||||
Enabled=0
|
||||
[pcbnew/Netclasses]
|
||||
[pcbnew/Netclasses/Default]
|
||||
Name=Default
|
||||
Clearance=0.2
|
||||
TrackWidth=0.25
|
||||
ViaDiameter=0.8
|
||||
ViaDrill=0.4
|
||||
uViaDiameter=0.3
|
||||
uViaDrill=0.1
|
||||
dPairWidth=0.2
|
||||
dPairGap=0.25
|
||||
dPairViaGap=0.25
|
||||
[pcbnew/Netclasses/1]
|
||||
Name=Power
|
||||
Clearance=0.2
|
||||
TrackWidth=0.35
|
||||
ViaDiameter=0.8
|
||||
ViaDrill=0.4
|
||||
uViaDiameter=0.3
|
||||
uViaDrill=0.1
|
||||
dPairWidth=0.2
|
||||
dPairGap=0.25
|
||||
dPairViaGap=0.25
|
440
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb.sch
Normal file
440
pcb/can_arduino_mini_pcb/can_arduino_mini_pcb.sch
Normal file
|
@ -0,0 +1,440 @@
|
|||
EESchema Schematic File Version 4
|
||||
EELAYER 30 0
|
||||
EELAYER END
|
||||
$Descr A4 11693 8268
|
||||
encoding utf-8
|
||||
Sheet 1 1
|
||||
Title ""
|
||||
Date ""
|
||||
Rev ""
|
||||
Comp ""
|
||||
Comment1 ""
|
||||
Comment2 ""
|
||||
Comment3 ""
|
||||
Comment4 ""
|
||||
$EndDescr
|
||||
$Comp
|
||||
L MCU_Module:Arduino_Nano_v3.x A1
|
||||
U 1 1 600ED8F8
|
||||
P 4850 3500
|
||||
F 0 "A1" H 4850 2411 50 0000 C CNN
|
||||
F 1 "Arduino_Nano_v3.x" H 4850 2320 50 0000 C CNN
|
||||
F 2 "Module:Arduino_Nano" H 4850 3500 50 0001 C CIN
|
||||
F 3 "http://www.mouser.com/pdfdocs/Gravitech_Arduino_Nano3_0.pdf" H 4850 3500 50 0001 C CNN
|
||||
1 4850 3500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R2
|
||||
U 1 1 600F00A2
|
||||
P 7550 4150
|
||||
F 0 "R2" V 7343 4150 50 0000 C CNN
|
||||
F 1 "330" V 7434 4150 50 0000 C CNN
|
||||
F 2 "Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P7.62mm_Horizontal" V 7480 4150 50 0001 C CNN
|
||||
F 3 "~" H 7550 4150 50 0001 C CNN
|
||||
1 7550 4150
|
||||
0 1 -1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R1
|
||||
U 1 1 600F0580
|
||||
P 7550 3950
|
||||
F 0 "R1" V 7343 3950 50 0000 C CNN
|
||||
F 1 "330" V 7434 3950 50 0000 C CNN
|
||||
F 2 "Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P7.62mm_Horizontal" V 7480 3950 50 0001 C CNN
|
||||
F 3 "~" H 7550 3950 50 0001 C CNN
|
||||
1 7550 3950
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:LED_RCGB D1
|
||||
U 1 1 600F1EA5
|
||||
P 7900 4150
|
||||
F 0 "D1" H 7900 3683 50 0000 C CNN
|
||||
F 1 "LED_RCGB" H 7900 3774 50 0000 C CNN
|
||||
F 2 "LED_THT:LED_D5.0mm-4_RGB" H 7900 4100 50 0001 C CNN
|
||||
F 3 "~" H 7900 4100 50 0001 C CNN
|
||||
1 7900 4150
|
||||
-1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Connector:Conn_01x15_Female J2
|
||||
U 1 1 600FC1CE
|
||||
P 6150 3900
|
||||
F 0 "J2" H 6178 3926 50 0000 L CNN
|
||||
F 1 "Conn_01x15_Female" H 6178 3835 50 0000 L CNN
|
||||
F 2 "Connector_PinSocket_2.54mm:PinSocket_1x15_P2.54mm_Vertical" H 6150 3900 50 0001 C CNN
|
||||
F 3 "~" H 6150 3900 50 0001 C CNN
|
||||
1 6150 3900
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Connector:Conn_01x15_Female J1
|
||||
U 1 1 601001CE
|
||||
P 3650 3400
|
||||
F 0 "J1" H 3542 2475 50 0000 C CNN
|
||||
F 1 "Conn_01x15_Female" H 3542 2566 50 0000 C CNN
|
||||
F 2 "Connector_PinSocket_2.54mm:PinSocket_1x15_P2.54mm_Vertical" H 3650 3400 50 0001 C CNN
|
||||
F 3 "~" H 3650 3400 50 0001 C CNN
|
||||
1 3650 3400
|
||||
-1 0 0 1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4350 4100 4300 4100
|
||||
Wire Wire Line
|
||||
4350 3900 3850 3900
|
||||
Wire Wire Line
|
||||
4350 3700 4200 3700
|
||||
Wire Wire Line
|
||||
4350 3600 4100 3600
|
||||
Wire Wire Line
|
||||
4350 3500 3850 3500
|
||||
Wire Wire Line
|
||||
4350 3300 4100 3300
|
||||
Wire Wire Line
|
||||
4350 3200 3850 3200
|
||||
Wire Wire Line
|
||||
4350 3100 4150 3100
|
||||
Wire Wire Line
|
||||
4350 3000 4300 3000
|
||||
Wire Wire Line
|
||||
4300 3000 4300 2700
|
||||
Wire Wire Line
|
||||
4300 2700 3850 2700
|
||||
Wire Wire Line
|
||||
4350 2900 4250 2900
|
||||
Wire Wire Line
|
||||
4250 2900 4250 2800
|
||||
Wire Wire Line
|
||||
4250 2800 3850 2800
|
||||
Wire Wire Line
|
||||
5400 1800 4200 1800
|
||||
Wire Wire Line
|
||||
4200 1800 4200 2900
|
||||
Wire Wire Line
|
||||
4200 2900 3850 2900
|
||||
$Comp
|
||||
L power:GND #PWR01
|
||||
U 1 1 6012CA0F
|
||||
P 3850 3000
|
||||
F 0 "#PWR01" H 3850 2750 50 0001 C CNN
|
||||
F 1 "GND" V 3855 2872 50 0000 R CNN
|
||||
F 2 "" H 3850 3000 50 0001 C CNN
|
||||
F 3 "" H 3850 3000 50 0001 C CNN
|
||||
1 3850 3000
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:GND #PWR04
|
||||
U 1 1 6012D65A
|
||||
P 4850 4500
|
||||
F 0 "#PWR04" H 4850 4250 50 0001 C CNN
|
||||
F 1 "GND" H 4855 4327 50 0000 C CNN
|
||||
F 2 "" H 4850 4500 50 0001 C CNN
|
||||
F 3 "" H 4850 4500 50 0001 C CNN
|
||||
1 4850 4500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:GND #PWR05
|
||||
U 1 1 6012DD3A
|
||||
P 4950 4500
|
||||
F 0 "#PWR05" H 4950 4250 50 0001 C CNN
|
||||
F 1 "GND" H 4955 4327 50 0000 C CNN
|
||||
F 2 "" H 4950 4500 50 0001 C CNN
|
||||
F 3 "" H 4950 4500 50 0001 C CNN
|
||||
1 4950 4500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
5350 3500 5950 3500
|
||||
Wire Wire Line
|
||||
5350 3600 5950 3600
|
||||
Wire Wire Line
|
||||
5350 3700 5950 3700
|
||||
Wire Wire Line
|
||||
5350 3800 5950 3800
|
||||
Wire Wire Line
|
||||
5350 4100 5950 4100
|
||||
Wire Wire Line
|
||||
5350 4200 5950 4200
|
||||
Wire Wire Line
|
||||
5750 4400 5950 4400
|
||||
$Comp
|
||||
L power:GND #PWR08
|
||||
U 1 1 60144FB1
|
||||
P 5950 4500
|
||||
F 0 "#PWR08" H 5950 4250 50 0001 C CNN
|
||||
F 1 "GND" V 5955 4372 50 0000 R CNN
|
||||
F 2 "" H 5950 4500 50 0001 C CNN
|
||||
F 3 "" H 5950 4500 50 0001 C CNN
|
||||
1 5950 4500
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:+5V #PWR09
|
||||
U 1 1 60146393
|
||||
P 5950 4600
|
||||
F 0 "#PWR09" H 5950 4450 50 0001 C CNN
|
||||
F 1 "+5V" V 5965 4728 50 0000 L CNN
|
||||
F 2 "" H 5950 4600 50 0001 C CNN
|
||||
F 3 "" H 5950 4600 50 0001 C CNN
|
||||
1 5950 4600
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:VCC #PWR07
|
||||
U 1 1 601470A5
|
||||
P 5950 4300
|
||||
F 0 "#PWR07" H 5950 4150 50 0001 C CNN
|
||||
F 1 "VCC" V 5965 4427 50 0000 L CNN
|
||||
F 2 "" H 5950 4300 50 0001 C CNN
|
||||
F 3 "" H 5950 4300 50 0001 C CNN
|
||||
1 5950 4300
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
5350 3300 5400 3300
|
||||
Wire Wire Line
|
||||
5400 3300 5400 3400
|
||||
Wire Wire Line
|
||||
5400 3400 5950 3400
|
||||
Wire Wire Line
|
||||
4350 4200 4350 4750
|
||||
Wire Wire Line
|
||||
4350 4750 6400 4750
|
||||
Wire Wire Line
|
||||
6400 4750 6400 3050
|
||||
Wire Wire Line
|
||||
6400 3050 5950 3050
|
||||
Wire Wire Line
|
||||
5950 3050 5950 3200
|
||||
$Comp
|
||||
L power:+3.3V #PWR06
|
||||
U 1 1 60156630
|
||||
P 5950 3300
|
||||
F 0 "#PWR06" H 5950 3150 50 0001 C CNN
|
||||
F 1 "+3.3V" V 5965 3428 50 0000 L CNN
|
||||
F 2 "" H 5950 3300 50 0001 C CNN
|
||||
F 3 "" H 5950 3300 50 0001 C CNN
|
||||
1 5950 3300
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:VCC #PWR03
|
||||
U 1 1 601722BB
|
||||
P 4500 5800
|
||||
F 0 "#PWR03" H 4500 5650 50 0001 C CNN
|
||||
F 1 "VCC" H 4515 5973 50 0000 C CNN
|
||||
F 2 "" H 4500 5800 50 0001 C CNN
|
||||
F 3 "" H 4500 5800 50 0001 C CNN
|
||||
1 4500 5800
|
||||
-1 0 0 1
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:GND #PWR012
|
||||
U 1 1 60176347
|
||||
P 8100 4150
|
||||
F 0 "#PWR012" H 8100 3900 50 0001 C CNN
|
||||
F 1 "GND" V 8105 4022 50 0000 R CNN
|
||||
F 2 "" H 8100 4150 50 0001 C CNN
|
||||
F 3 "" H 8100 4150 50 0001 C CNN
|
||||
1 8100 4150
|
||||
0 -1 1 0
|
||||
$EndComp
|
||||
NoConn ~ 7700 4350
|
||||
$Comp
|
||||
L Connector:Conn_01x02_Female J3
|
||||
U 1 1 601B1E80
|
||||
P 6800 5150
|
||||
F 0 "J3" H 6828 5126 50 0000 L CNN
|
||||
F 1 "Conn_01x02_Female" H 6828 5035 50 0000 L CNN
|
||||
F 2 "Connector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_Vertical" H 6800 5150 50 0001 C CNN
|
||||
F 3 "~" H 6800 5150 50 0001 C CNN
|
||||
1 6800 5150
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:GND #PWR010
|
||||
U 1 1 601B2F1D
|
||||
P 6600 5150
|
||||
F 0 "#PWR010" H 6600 4900 50 0001 C CNN
|
||||
F 1 "GND" V 6605 5022 50 0000 R CNN
|
||||
F 2 "" H 6600 5150 50 0001 C CNN
|
||||
F 3 "" H 6600 5150 50 0001 C CNN
|
||||
1 6600 5150
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:+5V #PWR011
|
||||
U 1 1 601B35EA
|
||||
P 6600 5250
|
||||
F 0 "#PWR011" H 6600 5100 50 0001 C CNN
|
||||
F 1 "+5V" V 6615 5378 50 0000 L CNN
|
||||
F 2 "" H 6600 5250 50 0001 C CNN
|
||||
F 3 "" H 6600 5250 50 0001 C CNN
|
||||
1 6600 5250
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:+3.3V #PWR014
|
||||
U 1 1 601B5CED
|
||||
P 4950 2500
|
||||
F 0 "#PWR014" H 4950 2350 50 0001 C CNN
|
||||
F 1 "+3.3V" H 4965 2673 50 0000 C CNN
|
||||
F 2 "" H 4950 2500 50 0001 C CNN
|
||||
F 3 "" H 4950 2500 50 0001 C CNN
|
||||
1 4950 2500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:VCC #PWR015
|
||||
U 1 1 601B6094
|
||||
P 5050 2500
|
||||
F 0 "#PWR015" H 5050 2350 50 0001 C CNN
|
||||
F 1 "VCC" H 5065 2673 50 0000 C CNN
|
||||
F 2 "" H 5050 2500 50 0001 C CNN
|
||||
F 3 "" H 5050 2500 50 0001 C CNN
|
||||
1 5050 2500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L power:+5V #PWR013
|
||||
U 1 1 601B69BB
|
||||
P 4750 2500
|
||||
F 0 "#PWR013" H 4750 2350 50 0001 C CNN
|
||||
F 1 "+5V" H 4765 2673 50 0000 C CNN
|
||||
F 2 "" H 4750 2500 50 0001 C CNN
|
||||
F 3 "" H 4750 2500 50 0001 C CNN
|
||||
1 4750 2500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L custom_components:CAN_MODULE U1
|
||||
U 1 1 601E578C
|
||||
P 4900 5500
|
||||
F 0 "U1" H 5128 5551 50 0000 L CNN
|
||||
F 1 "CAN_MODULE" H 5128 5460 50 0000 L CNN
|
||||
F 2 "Zeusbadge:logo_small" H 4400 5550 50 0001 C CNN
|
||||
F 3 "" H 4400 5550 50 0001 C CNN
|
||||
1 4900 5500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Connector:Conn_01x07_Female J4
|
||||
U 1 1 60215342
|
||||
P 4700 5500
|
||||
F 0 "J4" H 4728 5526 50 0000 L CNN
|
||||
F 1 "Conn_01x07_Female" H 4728 5435 50 0000 L CNN
|
||||
F 2 "Connector_PinSocket_2.54mm:PinSocket_1x07_P2.54mm_Vertical" H 4700 5500 50 0001 C CNN
|
||||
F 3 "~" H 4700 5500 50 0001 C CNN
|
||||
1 4700 5500
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4350 4750 4350 5300
|
||||
Wire Wire Line
|
||||
4350 5300 4500 5300
|
||||
Connection ~ 4350 4750
|
||||
Connection ~ 4500 5300
|
||||
Wire Wire Line
|
||||
3850 3800 4350 3800
|
||||
Wire Wire Line
|
||||
3850 3400 4350 3400
|
||||
Wire Wire Line
|
||||
3850 4000 4250 4000
|
||||
Wire Wire Line
|
||||
4300 4100 4300 5500
|
||||
Wire Wire Line
|
||||
4300 5500 4500 5500
|
||||
Connection ~ 4300 4100
|
||||
Wire Wire Line
|
||||
4300 4100 3850 4100
|
||||
Connection ~ 4500 5500
|
||||
Wire Wire Line
|
||||
4500 5400 4250 5400
|
||||
Wire Wire Line
|
||||
4250 5400 4250 4000
|
||||
Connection ~ 4500 5400
|
||||
Connection ~ 4250 4000
|
||||
Wire Wire Line
|
||||
4250 4000 4350 4000
|
||||
Wire Wire Line
|
||||
4200 3700 4200 5600
|
||||
Wire Wire Line
|
||||
4200 5600 4500 5600
|
||||
Connection ~ 4200 3700
|
||||
Wire Wire Line
|
||||
4200 3700 3850 3700
|
||||
Connection ~ 4500 5600
|
||||
$Comp
|
||||
L power:GND #PWR02
|
||||
U 1 1 60237003
|
||||
P 4500 5700
|
||||
F 0 "#PWR02" H 4500 5450 50 0001 C CNN
|
||||
F 1 "GND" V 4505 5572 50 0000 R CNN
|
||||
F 2 "" H 4500 5700 50 0001 C CNN
|
||||
F 3 "" H 4500 5700 50 0001 C CNN
|
||||
1 4500 5700
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
Connection ~ 4500 5700
|
||||
Connection ~ 4500 5800
|
||||
Wire Wire Line
|
||||
5350 2900 5750 2900
|
||||
Wire Wire Line
|
||||
5750 2900 5750 4400
|
||||
Wire Wire Line
|
||||
5350 3000 5400 3000
|
||||
Wire Wire Line
|
||||
5400 3000 5400 1800
|
||||
$Comp
|
||||
L Device:Jumper_NO_Small JP1
|
||||
U 1 1 602581FC
|
||||
P 4500 5100
|
||||
F 0 "JP1" V 4454 5148 50 0000 L CNN
|
||||
F 1 "Jumper_NO_Small" V 4545 5148 50 0000 L CNN
|
||||
F 2 "Jumper:SolderJumper-2_P1.3mm_Open_TrianglePad1.0x1.5mm" H 4500 5100 50 0001 C CNN
|
||||
F 3 "~" H 4500 5100 50 0001 C CNN
|
||||
1 4500 5100
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
Connection ~ 4500 5200
|
||||
Wire Wire Line
|
||||
4500 5000 4500 4500
|
||||
Wire Wire Line
|
||||
4500 4500 4150 4500
|
||||
Wire Wire Line
|
||||
4150 4500 4150 3100
|
||||
Connection ~ 4150 3100
|
||||
Wire Wire Line
|
||||
4150 3100 3850 3100
|
||||
Wire Wire Line
|
||||
5350 4000 5950 4000
|
||||
Wire Wire Line
|
||||
5350 3900 5950 3900
|
||||
Wire Wire Line
|
||||
7400 3950 7400 1700
|
||||
Wire Wire Line
|
||||
7400 1700 3450 1700
|
||||
Wire Wire Line
|
||||
3450 1700 3450 3250
|
||||
Wire Wire Line
|
||||
3450 3250 4100 3250
|
||||
Wire Wire Line
|
||||
4100 3250 4100 3300
|
||||
Connection ~ 4100 3300
|
||||
Wire Wire Line
|
||||
4100 3300 3850 3300
|
||||
Wire Wire Line
|
||||
7400 4150 7100 4150
|
||||
Wire Wire Line
|
||||
7100 4150 7100 6050
|
||||
Wire Wire Line
|
||||
7100 6050 4100 6050
|
||||
Wire Wire Line
|
||||
4100 6050 4100 3600
|
||||
Connection ~ 4100 3600
|
||||
Wire Wire Line
|
||||
4100 3600 3850 3600
|
||||
$EndSCHEMATC
|
3
pcb/can_arduino_mini_pcb/custom_components.dcm
Normal file
3
pcb/can_arduino_mini_pcb/custom_components.dcm
Normal file
|
@ -0,0 +1,3 @@
|
|||
EESchema-DOCLIB Version 2.0
|
||||
#
|
||||
#End Doc Library
|
23
pcb/can_arduino_mini_pcb/custom_components.lib
Normal file
23
pcb/can_arduino_mini_pcb/custom_components.lib
Normal file
|
@ -0,0 +1,23 @@
|
|||
EESchema-LIBRARY Version 2.4
|
||||
#encoding utf-8
|
||||
#
|
||||
# CAN_MODULE
|
||||
#
|
||||
DEF CAN_MODULE U 0 40 Y Y 1 F N
|
||||
F0 "U" -250 -400 50 H V C CNN
|
||||
F1 "CAN_MODULE" -50 400 50 H V C CNN
|
||||
F2 "" -500 50 50 H I C CNN
|
||||
F3 "" -500 50 50 H I C CNN
|
||||
DRAW
|
||||
P 5 0 1 0 -300 350 -300 -350 200 -350 200 350 -300 350 f
|
||||
X CS ~ -400 -100 100 R 50 50 1 1 I
|
||||
X GND ~ -400 -200 100 R 50 50 1 1 W
|
||||
X INT ~ -400 300 100 R 50 50 1 1 O
|
||||
X SCK ~ -400 200 100 R 50 50 1 1 I
|
||||
X SI ~ -400 100 100 R 50 50 1 1 I
|
||||
X SO ~ -400 0 100 R 50 50 1 1 O
|
||||
X VCC ~ -400 -300 100 R 50 50 1 1 W
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
3
pcb/can_arduino_mini_pcb/fp-lib-table
Normal file
3
pcb/can_arduino_mini_pcb/fp-lib-table
Normal file
|
@ -0,0 +1,3 @@
|
|||
(fp_lib_table
|
||||
(lib (name can_arduino_mini_pcb)(type KiCad)(uri ${KIPRJMOD}/can_arduino_mini_pcb.pretty)(options "")(descr ""))
|
||||
)
|
3
pcb/can_arduino_mini_pcb/sym-lib-table
Normal file
3
pcb/can_arduino_mini_pcb/sym-lib-table
Normal file
|
@ -0,0 +1,3 @@
|
|||
(sym_lib_table
|
||||
(lib (name custom_components)(type Legacy)(uri ${KIPRJMOD}/custom_components.lib)(options "")(descr ""))
|
||||
)
|
2
pcb/panel/build.sh
Executable file
2
pcb/panel/build.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
kikit panelize grid --space 3 --gridsize 1 2 --tabwidth 5 --tabheight 10 --htabs 1 --vtabs 1 --mousebites 0.5 1 0.25 --radius 1 ../can_arduino_mini_pcb/can_arduino_mini_pcb.kicad_pcb can_arduino_mini_pcb_panel/can_arduino_mini_pcb_panel.kicad_pcb
|
28
pcb/panel/can_arduino_mini_pcb_panel/.gitignore
vendored
Normal file
28
pcb/panel/can_arduino_mini_pcb_panel/.gitignore
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
# For PCBs designed using KiCad: http://www.kicad-pcb.org/
|
||||
# Format documentation: http://kicad-pcb.org/help/file-formats/
|
||||
|
||||
# Temporary files
|
||||
*.000
|
||||
*.bak
|
||||
*.bck
|
||||
*.kicad_pcb-bak
|
||||
*.kicad_sch-bak
|
||||
*.kicad_prl
|
||||
*.sch-bak
|
||||
*~
|
||||
_autosave-*
|
||||
*.tmp
|
||||
*-save.pro
|
||||
*-save.kicad_pcb
|
||||
fp-info-cache
|
||||
|
||||
# Netlist files (exported from Eeschema)
|
||||
*.net
|
||||
|
||||
# Autorouter files (exported from Pcbnew)
|
||||
*.dsn
|
||||
*.ses
|
||||
|
||||
# Exported BOM files
|
||||
*.xml
|
||||
*.csv
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,33 @@
|
|||
update=22/05/2015 07:44:53
|
||||
version=1
|
||||
last_client=kicad
|
||||
[general]
|
||||
version=1
|
||||
RootSch=
|
||||
BoardNm=
|
||||
[pcbnew]
|
||||
version=1
|
||||
LastNetListRead=
|
||||
UseCmpFile=1
|
||||
PadDrill=0.600000000000
|
||||
PadDrillOvalY=0.600000000000
|
||||
PadSizeH=1.500000000000
|
||||
PadSizeV=1.500000000000
|
||||
PcbTextSizeV=1.500000000000
|
||||
PcbTextSizeH=1.500000000000
|
||||
PcbTextThickness=0.300000000000
|
||||
ModuleTextSizeV=1.000000000000
|
||||
ModuleTextSizeH=1.000000000000
|
||||
ModuleTextSizeThickness=0.150000000000
|
||||
SolderMaskClearance=0.000000000000
|
||||
SolderMaskMinWidth=0.000000000000
|
||||
DrawSegmentWidth=0.200000000000
|
||||
BoardOutlineThickness=0.100000000000
|
||||
ModuleOutlineThickness=0.150000000000
|
||||
[cvpcb]
|
||||
version=1
|
||||
NetIExt=net
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
[eeschema/libraries]
|
|
@ -0,0 +1,4 @@
|
|||
EESchema Schematic File Version 2
|
||||
EELAYER 25 0
|
||||
EELAYER END
|
||||
$EndSCHEMATC
|
BIN
pcb/panel/can_arduino_mini_pcb_panel/fabricate/handin.zip
Normal file
BIN
pcb/panel/can_arduino_mini_pcb_panel/fabricate/handin.zip
Normal file
Binary file not shown.
BIN
pcb/pcb_kicad.png
Normal file
BIN
pcb/pcb_kicad.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 359 KiB |
|
@ -34,6 +34,7 @@ uint8_t state = STATE_INACTIVE;
|
|||
struct obus_can::module connected_modules_ids[OBUS_MAX_MODULES];
|
||||
uint8_t nr_connected_modules;
|
||||
uint8_t nr_connected_puzzles;
|
||||
uint8_t nr_solved_puzzles;
|
||||
uint8_t strikes;
|
||||
|
||||
// Bitvector for checking if game is solved or not
|
||||
|
@ -94,6 +95,9 @@ void add_puzzle_to_bit_vector(uint8_t module_id) {
|
|||
void solve_puzzle_in_bit_vector(uint8_t module_id) {
|
||||
uint8_t byte_index = module_id >> 3;
|
||||
uint8_t bit_index = module_id & 0x07;
|
||||
if (unsolved_puzzles[byte_index] & (0x1 << bit_index)) {
|
||||
nr_solved_puzzles++;
|
||||
}
|
||||
unsolved_puzzles[byte_index] &= ~(0x1 << bit_index);
|
||||
}
|
||||
|
||||
|
@ -175,7 +179,7 @@ void receive_hello() {
|
|||
Serial.println(F("W Max # modules reached"));
|
||||
}
|
||||
|
||||
obus_can::send_c_ack(this_module);
|
||||
obus_can::send_c_ack(this_module, msg.from);
|
||||
Serial.println(" ACK");
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +193,7 @@ void initialize_game() {
|
|||
}
|
||||
|
||||
strikes = 0;
|
||||
nr_solved_puzzles = 0;
|
||||
game_start = millis();
|
||||
|
||||
last_draw = 0;
|
||||
|
@ -198,7 +203,7 @@ void initialize_game() {
|
|||
Serial.println(" Game started");
|
||||
|
||||
draw_display(millis(), OBUS_GAME_DURATION_MS);
|
||||
obus_can::send_c_gamestart(this_module, OBUS_GAME_DURATION_MS, strikes, OBUS_MAX_STRIKES);
|
||||
obus_can::send_c_gamestart(this_module, OBUS_GAME_DURATION_MS, strikes, OBUS_MAX_STRIKES, nr_connected_puzzles);
|
||||
}
|
||||
|
||||
|
||||
|
@ -254,14 +259,14 @@ void game_loop() {
|
|||
|
||||
if (check_solved()) {
|
||||
Serial.println(" Game solved");
|
||||
obus_can::send_c_solved(this_module, time_left, strikes, OBUS_MAX_STRIKES);
|
||||
obus_can::send_c_solved(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles);
|
||||
state = STATE_GAMEOVER;
|
||||
tm.displayText("dISArmEd");
|
||||
return;
|
||||
}
|
||||
if (time_left == 0) {
|
||||
Serial.println(" Time's up");
|
||||
obus_can::send_c_timeout(this_module, time_left, strikes, OBUS_MAX_STRIKES);
|
||||
obus_can::send_c_timeout(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles);
|
||||
state = STATE_GAMEOVER;
|
||||
tm.displayText(" boo t");
|
||||
// m
|
||||
|
@ -271,7 +276,7 @@ void game_loop() {
|
|||
}
|
||||
if (strikes >= OBUS_MAX_STRIKES) {
|
||||
Serial.println(" Strikeout");
|
||||
obus_can::send_c_strikeout(this_module, time_left, strikes, OBUS_MAX_STRIKES);
|
||||
obus_can::send_c_strikeout(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles);
|
||||
state = STATE_GAMEOVER;
|
||||
tm.displayText(" boo S");
|
||||
// m
|
||||
|
@ -283,7 +288,7 @@ void game_loop() {
|
|||
draw_display(current_time, time_left);
|
||||
|
||||
if (last_update + OBUS_UPDATE_INTERVAL <= current_time) {
|
||||
obus_can::send_c_state(this_module, time_left, strikes, OBUS_MAX_STRIKES);
|
||||
obus_can::send_c_state(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles);
|
||||
last_update = current_time;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,8 +58,9 @@ void loop() {
|
|||
}
|
||||
}
|
||||
|
||||
void callback_game_start() {
|
||||
|
||||
void callback_game_start(uint8_t puzzle_modules_connected) {
|
||||
// Intentionally emtpy
|
||||
(void)puzzle_modules_connected;
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
6
src/modules/puzzle_testmodule_buttons/doc/index.md
Normal file
6
src/modules/puzzle_testmodule_buttons/doc/index.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
## Testmodule buttons
|
||||
|
||||
If the blue LED is lit, press the green button, otherwise press the red button.
|
||||
|
||||
### Credits
|
||||
Module developed by redfast00.
|
|
@ -0,0 +1,69 @@
|
|||
// (c) 2020, redfast00
|
||||
// See the LICENSE file for conditions for copying
|
||||
|
||||
|
||||
// A red button connected to pin 5
|
||||
// A green button connected to pin 6
|
||||
// A blue led (with 330 ohm resistor) connected to pin 9
|
||||
|
||||
#include <obus_module.h>
|
||||
#include <ezButton.h>
|
||||
|
||||
#define BLUE_LED 9
|
||||
ezButton red_button(5);
|
||||
ezButton green_button(6);
|
||||
|
||||
bool blue_state = false;
|
||||
bool checking_input = false;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
obus_module::setup(OBUS_TYPE_PUZZLE, OBUS_PUZZLE_ID_DEVELOPMENT);
|
||||
red_button.setDebounceTime(100);
|
||||
green_button.setDebounceTime(100);
|
||||
pinMode(BLUE_LED, OUTPUT);
|
||||
}
|
||||
|
||||
obus_can::message message;
|
||||
|
||||
void loop() {
|
||||
bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop);
|
||||
// TODO handle update frames (not needed for this module, but could be useful as example code)
|
||||
|
||||
red_button.loop();
|
||||
green_button.loop();
|
||||
|
||||
if (checking_input) {
|
||||
if (red_button.getCount() > 0) {
|
||||
if (blue_state) {
|
||||
obus_module::strike();
|
||||
} else {
|
||||
obus_module::solve();
|
||||
checking_input = blue_state = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (green_button.getCount() > 0) {
|
||||
if (blue_state) {
|
||||
obus_module::solve();
|
||||
checking_input = blue_state = false;
|
||||
} else {
|
||||
obus_module::strike();
|
||||
}
|
||||
}
|
||||
}
|
||||
red_button.resetCount();
|
||||
green_button.resetCount();
|
||||
|
||||
digitalWrite(BLUE_LED, blue_state);
|
||||
}
|
||||
|
||||
void callback_game_start(uint8_t puzzle_modules_connected) {
|
||||
(void)puzzle_modules_connected;
|
||||
blue_state = random(0, 2);
|
||||
checking_input = true;
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
||||
blue_state = checking_input = false;
|
||||
}
|
131
src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino
Normal file
131
src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino
Normal file
|
@ -0,0 +1,131 @@
|
|||
// (c) 2020, timpy
|
||||
// See the LICENSE file for conditions for copying
|
||||
|
||||
#include <obus_module.h>
|
||||
#include <ezButton.h>
|
||||
|
||||
|
||||
// yellow
|
||||
#define DATE_CLOCK_PIN 6
|
||||
// orange
|
||||
#define DATE_DATA_PIN 7
|
||||
// green
|
||||
#define DATE_READ_PIN 5
|
||||
|
||||
// Solve button
|
||||
#define DATE_SOLVE_BTN 3
|
||||
|
||||
#define DATE_MODE_STOP 1
|
||||
#define DATE_MODE_1S 2
|
||||
#define DATE_MODE_10S 4
|
||||
#define DATE_MODE_1M 8
|
||||
#define DATE_MODE_10M 16
|
||||
#define DATE_MODE_TIME_IN 32
|
||||
#define DATE_MODE_DATE_IN 64
|
||||
#define DATE_MODE_REAL_OUT 128
|
||||
#define DATE_MODE_NORM_OUT 0
|
||||
|
||||
|
||||
uint8_t correct_code[4] = {
|
||||
DATE_MODE_STOP,
|
||||
12,
|
||||
34,
|
||||
56
|
||||
};
|
||||
|
||||
ezButton solve_button(DATE_SOLVE_BTN);
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
obus_module::setup(OBUS_TYPE_PUZZLE, 123);
|
||||
solve_button.setDebounceTime(10);
|
||||
solve_button.setCountMode(COUNT_RISING);
|
||||
setup_date_module();
|
||||
}
|
||||
|
||||
obus_can::message message;
|
||||
|
||||
void loop() {
|
||||
bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop);
|
||||
// TODO handle update frames (not needed for this module, but could be useful as example code)
|
||||
solve_button.loop();
|
||||
if (solve_button.getCount() > 0) {
|
||||
uint8_t data[4];
|
||||
read_from_date_module(data);
|
||||
|
||||
if (check_date_code(data)) {
|
||||
Serial.println("SOLVED!");
|
||||
obus_module::solve();
|
||||
} else {
|
||||
Serial.println("STRIKE!");
|
||||
obus_module::strike();
|
||||
}
|
||||
solve_button.resetCount();
|
||||
}
|
||||
}
|
||||
|
||||
void setup_date_module() {
|
||||
pinMode(DATE_CLOCK_PIN, OUTPUT);
|
||||
pinMode(DATE_DATA_PIN, INPUT);
|
||||
pinMode(DATE_READ_PIN, OUTPUT);
|
||||
}
|
||||
|
||||
uint8_t read_value_from_date_module(uint8_t bit_order) {
|
||||
|
||||
digitalWrite(DATE_CLOCK_PIN, LOW);
|
||||
uint8_t value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t read_bit = digitalRead(DATE_DATA_PIN);
|
||||
if (bit_order == LSBFIRST)
|
||||
value |= read_bit << i;
|
||||
else
|
||||
value |= read_bit << (7 - i);
|
||||
digitalWrite(DATE_CLOCK_PIN, HIGH);
|
||||
delayMicroseconds(3);
|
||||
digitalWrite(DATE_CLOCK_PIN, LOW);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void read_from_date_module(uint8_t* data_out) {
|
||||
digitalWrite(DATE_READ_PIN, HIGH);
|
||||
delayMicroseconds(3);
|
||||
digitalWrite(DATE_READ_PIN, LOW);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
data_out[i] = read_value_from_date_module(LSBFIRST);
|
||||
}
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
// Convert raw data to human interpretable number
|
||||
data_out[i] = 10*(data_out[i] & 0x0F) + ((data_out[i] & 0xF0) >> 4);
|
||||
}
|
||||
|
||||
|
||||
//for (int i = 0; i < 4; i++) {
|
||||
// Serial.print(data_out[i]);
|
||||
// Serial.print(" ");
|
||||
//}
|
||||
|
||||
//Serial.println();
|
||||
digitalWrite(DATE_CLOCK_PIN, LOW);
|
||||
}
|
||||
|
||||
bool check_date_code(uint8_t* code) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (code[i] != correct_code[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void callback_game_start(uint8_t puzzle_modules_connected) {
|
||||
// Intentionally emtpy
|
||||
(void)puzzle_modules_connected;
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
||||
// Intentionally empty
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// (c) 2020, redfast00
|
||||
// See the LICENSE file for conditions for copying
|
||||
|
||||
#include <obus_module.h>
|
||||
#include <ezButton.h>
|
||||
|
||||
ezButton red_button(5);
|
||||
ezButton green_button(6);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
obus_module::setup(OBUS_TYPE_PUZZLE, OBUS_PUZZLE_ID_DEVELOPMENT);
|
||||
red_button.setDebounceTime(100);
|
||||
green_button.setDebounceTime(100);
|
||||
}
|
||||
|
||||
obus_can::message message;
|
||||
|
||||
void loop() {
|
||||
bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop);
|
||||
// TODO handle update frames (not needed for this module, but could be useful as example code)
|
||||
|
||||
red_button.loop();
|
||||
green_button.loop();
|
||||
|
||||
if (red_button.getCount() > 0) {
|
||||
red_button.resetCount();
|
||||
obus_module::strike();
|
||||
}
|
||||
|
||||
if (green_button.getCount() > 0) {
|
||||
green_button.resetCount();
|
||||
obus_module::solve();
|
||||
}
|
||||
}
|
||||
|
||||
void callback_game_start() {
|
||||
// Intentionally emtpy
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
||||
// Intentionally empty
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
## Testmodule buttons
|
||||
|
||||
Don't press the red button. Press the green button to solve the module.
|
||||
|
||||
### Credits
|
||||
Module developed by redfast00.
|
|
@ -1,130 +0,0 @@
|
|||
// (c) 2020, timpy
|
||||
// See the LICENSE file for conditions for copying
|
||||
|
||||
#include <obus_module.h>
|
||||
#include <ezButton.h>
|
||||
|
||||
|
||||
// yellow
|
||||
#define DATE_CLOCK_PIN 6
|
||||
// orange
|
||||
#define DATE_DATA_PIN 7
|
||||
// green
|
||||
#define DATE_READ_PIN 5
|
||||
|
||||
// Solve button
|
||||
#define DATE_SOLVE_BTN 3
|
||||
|
||||
#define DATE_MODE_STOP 1
|
||||
#define DATE_MODE_1S 2
|
||||
#define DATE_MODE_10S 4
|
||||
#define DATE_MODE_1M 8
|
||||
#define DATE_MODE_10M 16
|
||||
#define DATE_MODE_TIME_IN 32
|
||||
#define DATE_MODE_DATE_IN 64
|
||||
#define DATE_MODE_REAL_OUT 128
|
||||
#define DATE_MODE_NORM_OUT 0
|
||||
|
||||
|
||||
uint8_t correct_code[4] = {
|
||||
DATE_MODE_STOP,
|
||||
12,
|
||||
34,
|
||||
56
|
||||
};
|
||||
|
||||
ezButton solve_button(DATE_SOLVE_BTN);
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
obus_module::setup(OBUS_TYPE_PUZZLE, 123);
|
||||
solve_button.setDebounceTime(10);
|
||||
solve_button.setCountMode(COUNT_RISING);
|
||||
setup_date_module();
|
||||
}
|
||||
|
||||
obus_can::message message;
|
||||
|
||||
void loop() {
|
||||
bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop);
|
||||
// TODO handle update frames (not needed for this module, but could be useful as example code)
|
||||
solve_button.loop();
|
||||
if (solve_button.getCount() > 0) {
|
||||
uint8_t data[4];
|
||||
read_from_date_module(data);
|
||||
|
||||
if (check_date_code(data)) {
|
||||
Serial.println("SOLVED!");
|
||||
obus_module::solve();
|
||||
} else {
|
||||
Serial.println("STRIKE!");
|
||||
obus_module::strike();
|
||||
}
|
||||
solve_button.resetCount();
|
||||
}
|
||||
}
|
||||
|
||||
void setup_date_module() {
|
||||
pinMode(DATE_CLOCK_PIN, OUTPUT);
|
||||
pinMode(DATE_DATA_PIN, INPUT);
|
||||
pinMode(DATE_READ_PIN, OUTPUT);
|
||||
}
|
||||
|
||||
uint8_t read_value_from_date_module(uint8_t bit_order) {
|
||||
|
||||
digitalWrite(DATE_CLOCK_PIN, LOW);
|
||||
uint8_t value = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t read_bit = digitalRead(DATE_DATA_PIN);
|
||||
if (bit_order == LSBFIRST)
|
||||
value |= read_bit << i;
|
||||
else
|
||||
value |= read_bit << (7 - i);
|
||||
digitalWrite(DATE_CLOCK_PIN, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(DATE_CLOCK_PIN, LOW);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void read_from_date_module(uint8_t* data_out) {
|
||||
digitalWrite(DATE_READ_PIN, HIGH);
|
||||
delay(200);
|
||||
digitalWrite(DATE_READ_PIN, LOW);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
data_out[i] = read_value_from_date_module(LSBFIRST);
|
||||
}
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
// Convert raw data to human interpretable number
|
||||
data_out[i] = 10*(data_out[i] & 0x0F) + ((data_out[i] & 0xF0) >> 4);
|
||||
}
|
||||
|
||||
|
||||
//for (int i = 0; i < 4; i++) {
|
||||
// Serial.print(data_out[i]);
|
||||
// Serial.print(" ");
|
||||
//}
|
||||
|
||||
//Serial.println();
|
||||
digitalWrite(DATE_CLOCK_PIN, LOW);
|
||||
}
|
||||
|
||||
bool check_date_code(uint8_t* code) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (code[i] != correct_code[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void callback_game_start() {
|
||||
// Intentionally emtpy
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
||||
// Intentionally empty
|
||||
}
|
|
@ -12,12 +12,16 @@ if [ ! -d ./template_module ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Ask for module type
|
||||
print "Type of module (puzzle/needy/info): "
|
||||
read module_type
|
||||
|
||||
# Ask for module name
|
||||
print "Name of module (e.g. Oil gauge): "
|
||||
read module_name
|
||||
|
||||
# Determine a "clean" module name for paths: lowercase, no spaces
|
||||
module="`print "$module_name" | tr [A-Z] [a-z] | sed "s/ /_/g;s/'//g"`"
|
||||
module="`print "${module_type}_${module_name}" | tr [A-Z] [a-z] | sed "s/ /_/g;s/'//g"`"
|
||||
|
||||
# Make sure `modules` directory exists and target directory doesn't
|
||||
mkdir -p modules
|
||||
|
@ -35,7 +39,19 @@ read author
|
|||
cp -r -- template_module "$module_dir"
|
||||
cd -- "$module_dir"
|
||||
|
||||
# Disallow % in fields that will be used in %-delimited ed substitution
|
||||
# Fill in the blanks in the template
|
||||
# `sed -i` is not portable so we create something like it ourselves
|
||||
sed_inplace="`mktemp`"
|
||||
cleanup_sed() { rm -f -- "$sed_inplace"; }
|
||||
trap cleanup_sed EXIT
|
||||
print '
|
||||
filename="$1"
|
||||
shift 1
|
||||
tmpfile="`mktemp`"
|
||||
sed "$@" -- "$filename" > "$tmpfile"
|
||||
mv -- "$tmpfile" "$filename"
|
||||
' > "$sed_inplace"
|
||||
chmod 0500 -- "$sed_inplace" # Make executable
|
||||
assert_no_percent() {
|
||||
case "$1" in
|
||||
*"%"*) println "$2 must not contain %" >&2; exit 1 ;;
|
||||
|
@ -44,25 +60,11 @@ assert_no_percent() {
|
|||
assert_no_percent "$author" "Author name"
|
||||
assert_no_percent "$module_name" "Module name"
|
||||
assert_no_percent "$module" "Module path name"
|
||||
|
||||
# Fill in the blanks in the template
|
||||
# `sed -i` is not portable so we create something like it ourselves
|
||||
reced() {
|
||||
for file in "$1"/*; do
|
||||
if [ -f "$file" ]; then
|
||||
ed "$file" <<HERE
|
||||
%s/{YEAR}/$(date +%Y)/
|
||||
%s%{AUTHOR}%$author%
|
||||
%s%{MODULE_NAME}%$module_name%
|
||||
%s%{MODULE}%$module%
|
||||
wq
|
||||
HERE
|
||||
elif [ -d "$file" ]; then
|
||||
reced "$file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
reced .
|
||||
find . -type f -exec "$sed_inplace" '{}' -e "
|
||||
s/{YEAR}/$(date +%Y)/
|
||||
s%{AUTHOR}%$author%
|
||||
s%{MODULE_NAME}%$module_name%
|
||||
s%{MODULE}%$module%" \;
|
||||
|
||||
# Arduino IDE requires .ino sketches to have the same name as their directory
|
||||
mv -- main.ino "$module.ino"
|
||||
|
|
|
@ -16,8 +16,8 @@ void setup() {
|
|||
obus_can::message message;
|
||||
|
||||
void loop() {
|
||||
bool is_message_valid = obus_module::loop_puzzle(&message, callback_game_start, callback_game_stop);
|
||||
// bool bool is_message_valid = obus_module::loop_needy(&message);
|
||||
bool is_message_valid = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop);
|
||||
// bool is_message_valid = obus_module::loopNeedy(&message, callback_game_start, callback_game_stop);
|
||||
}
|
||||
|
||||
void callback_game_start() {
|
||||
|
|
Loading…
Reference in a new issue