J1939 - Yamaha Rudder Position ADDRESS - codesys

Using a PCAN VIEW, I determined the "rudder position" address (Yamaha Outboard), to be 166792448, and using CAN_Rx_MessageProc_ST_0 got the outboard position from bytes 4 and 5 of the 8 byte array:
RUDDER_ANGLE_RAW := WORD_TO_INT((256*MESSAGE_RX_NMEA[5]) + MESSAGE_RX_NMEA[4]);
I assumed that this Address would stay constant, but when the outboard changed, the address also changed - new address was 166792453. And further to this, after a power cycle, the address changed again to 166792456.
Assuming this has to do with address claiming, conflict, and the address changing.
The questions I have (and I have tried to grasp concepts but as a newby here am struggling) are thus:
1 Is there a range within in which this address will stay?
2 Can I get information out of the 8 byte received data (such as "yamaha outboard" or manufacturer specific info) that I could use to determine what the actual address is?
IF there is a range, I could write a procedure to scan the range, looking for the manufacturer ID, and thus determine the correct address.
Any help appreciated would be appreciated!

Related

ModBus to Click PLC

Looking for help with understanding how to change value in address DS1 (400001). First the click appears to use a 6 digit Modbus so not sure how to deal with the in 2 bytes. I think I read 40001 is the same but do not see how. I am able to receive data and understand the data when the Click PLC is the master. I would like my PC to be the master and change the address.
Here is the data I am sending to the PLC. I am expecting this data to be sent to PLC slave 02 and change the data in DS1 (400001) to the value of zero.
frame(0) = 2 'Slave Address =2
frame(1) = 6 'Mode =6
frame(2) = CByte(40001 / 256) '
frame(3) = CByte(40001 Mod 256) '
frame(4) = 0 '
frame(5) = 0 '
Dim crc As Byte() = CRC(frame) ' Call CRC Calculate.
frame(6) = crc(0) '=59 Error Check Lo
frame(7) = crc(1) '=189 Error Check Hi
SerialPort1.Write(frame, 0, frame.Length)
Realize that Application Layer addressing in Modbus is different than the bytes on the wire. The leading digit in an application layer address (e.g. 4xxxx for Holding Register) is implied in the function code (e.g. Read Holding Register)
So on the wire, you drop the leading 4, and left with an offset of 1-65536 (yes, Application Layer offsets are 1-based). But on the WIRE, they are 0-based, so you then subtact 1 from the offset to get the value 0-65535.
So, sometimes you see Application Modbus HRs like 4001, 40001, or 400001, all referencing the first HR in the device. 5 digit is most common. I do see 4 digit for old RTU devices. I do see a 6 digit every once in a while where the remote device has a ton of memory (or not, like Click).
Realize that a lot of devices are implemented by people who only understand the low level protocol, so when they say something is at address 40001, it may actually be at offset 0x0001, or 0x0000 (the correct offset on the wire). I even saw one implementation that implemented the address 40001 as literally 0x9C41 on the wire (maybe 0x9C40). Yes, 6 digit Application Layer Holding Register 440001.

mapping virtual address (logical address) to physical address

This question refers to an architecture using segmentation with paging. In this architecture, the 32-bit virtual address is divided into fields as follows:
                       4 bit segment number | 12 bit page number |
16 bit offset
Find the physical address corresponding to each of the following virtual addresses (answer "bad virtual address" if the virtual address is invalid).
1.00000000
2.20022002
3.10015555
Please help me with this, i dont know how to create page table and segment table for this mapping !!!
You are a little shy on details, so lets fill in a few:
Each segment has a 4096 (=2^12) entry translation table associated with it; otherwise it would not be interesting.
Each entry will contain a physical base address.
The extra offset will be added to this base address to find the final one.
So, in this hypothetical MMU, we could have a function like:
paddr_t translate(uint32_t vaddr) {
return segment[vaddr>>28].page[(vaddr>>16)&0xfff] + (vaddr & 0xffff);
}
A real (useful) mmu would have a bit more like:
paddr_t translate(uint32_t vaddr) {
seg_t *seg;
page_t *page;
if ((seg = segment[vaddr>>28]) && (page = seg->pagetab[(vaddr>>16)&0xfff])) {
return page->base + (vaddr & 0xffff);
} else {
raise(SEGV);
}
}
this is showing the sparseness of both segments and page mappings. It would likely have some permissions, as well, but this should help get you to the next obstacle.

Device tree address and reg and property

I'm struggling to understand where to get the address of a device on a device tree? As an example how do I know that I should set <0x00900000 0x20000> in here.
Is memory mapped IO done in the hardware (the processor itself) or in software and do I just have to pass the right address in the device tree?
Is the address hardcoded on the processor or can I just set an arbitrary address? I cannot find anything in my reference manual about setting a certain address in the device tree
These kind of addresses can be found in the Reference Manual of the processor.
You can find the link here.
Take a look at the chapter 48 (OCRAM On-chip RAM Memory Controller) and more specifically at the section 48.2.1 (page 4118):
The total on-chip RAM size for the chip is 128 Kbytes, organized as 16K x 64 bits,mapped from 0x00900000 to 0x0091FFFF
This is where come from the values <0x00900000 0x20000> from the dtsi file, corresponding to the base address and the offset.
These values are in dts/dtsi file provided by the chip maker.

CJ1W-CT021 Card Error Omron PLC

I got this error on a CJ1W-CT021 card. It happen all of a sudden after its been running the program for some time. How i found it was by going to the IO Table and Unit Set up. Clicked on parameters for that card and found two settings in red.
Output Control Mode and And/Or Counter Output Patterns. This was there reading
Output Control Mode = 0x40 No Applicable Set Data
And/Or Counter Output Patterns = 0x64 No Applicable Set Data
no idea on how or why these would change they should of been
Output Control Mode = Range Mode
And/Or Counter Output Patterns = Logically Or
I have added some new code, but nothing big or really even used as i had the outputs of the new rungs jumped out. One thing i thought might cause this is every cycle of the program it was checking the value of an encoder connected to this card. Maybe checking it too offten? Anyhow if anyone has any idea what these do or how they would change please post.
Thanks
Glen
EDIT.. I wanted to add the bits i used, dont think any are part of this cards internal io but i may be wrong?
Work bits 66.01 - 66.06 , 60.02 - 60.07 , 160.12, 160.01 - 160.04, 161.02, 161.03
and
Data Bits (D)20720, 20500, 20600, 20000, 20590, 20040
I would check section 4-1 through 4-2-4 of the CT021 manual - make sure you aren't writing to reserved memory locations used for configuration data of the CT021 unit.
EDIT:
1) Check Page 26 of the above manual to see the location of the machine switch settings. The bottom dial sets the '1's digit and the top dial sets the '10's digit (ie machine number can be 0-99);
2) Per page 94, D-Memory is allocated from D20000 + (N X 100) (400 Words) where N is equal to the machine number.
I would guess that your machine number is set to 0 (ie: both dials at '0'), 5, or 6. In the case of machine number '0', this would make the reserved DM range D20000 -> D20399. In this case (see pages 97, 105) D20000 would contain configuration data for Output Control Mode (bits 00-07) and Counter Output Patterns (bits 08-15). It looks like you are writing 0x6440 to D20000 (or D20500, D20600 for machine number 5 or 6, respectively) and are corrupting the configuration data.
If your machine number is 0 then stay away from D20000-D20399 unless you are directly trying to modify the counter's configuration state (ie: don't use them in your program!).
If the machine number is 1 then likewise for D20100-D20499, etc. If you have multiple counters they can overlap ranges so they should always be set with machine numbers which are 4 apart from each other.

What data type should I use to store an IP Address?

I suddenly just thought of this and got stuck deciding which data type should I use to store an IP Address?
I have thought of NSString; But if I would need the last digit for identifications, should I use float or double? And that is also another problem, since when can float or double have more than 1 decimal point?
I am probably asking the question wrongly, because I really don't know how to ask this.
The IP Address comes from an XML format <IP>192.168.1.1</IP>. Any idea how I should do this?
Use NSString. You are not going to do arithmetic with it. If you need the separate components you can use NSArray, but NSString will serve you well for just storing the IP address.
In response to your needs, you can always obtain the last character in your string using the NSString method:
NSString *lastCharacter = [ip_string substringFromIndex: [ip_string length] - 1];
Where ip_string is the string holding the IP address.
Edit in response to comment:
Logan's code is storing each element in the IP address separated by a period into an array. So if the IP address is 192.168.1.1, the array will equal (192, 168, 1, 1).
My code is storing the entire IP address in a string, and then obtaining the last character in that string. [ip_string substringFromIndex: [ip_string length] - 1] is just obtaining the last character in the string containing the IP address. The last character can be found at minus one character.
So if the IP address is 192.168.1.1, the lastCharacter string will just contain the number 1.
I suggested that code because you stated that you needed to do something with the last character in your IP address string, and my code shows how you can obtain the last character.
Use a string. You don't need to perform arithmetic on the IP do you?
It is typical to store IP addresses as strings, or arrays of integers. Another option is to store it as a 32 bit integer. It really comes down to what you want to do.
I would use NSString. If you need to get it piece by piece, use:
NSArray *pieces = [ipAddress componentsSeparatedByString: #"."];
192.168.1.1 is considered the default IP for numerous home high-speed wireless routers. It had been initially utilized by Linksys and yet has been seen used in a number of other home network products including some of those manufactured by Netgear and also Westell among others.
Even though IP address stands out as the default ip for a lot of high speed broadband wireless routers, this does not essentially has to be. A large number of producers set the default IP address to 192.168.1.1 as a way to market a standard precessing conditions and to make it simpler for very first time clients to setup their own networking systems simply and efficiently.
May only Linksys as well as other wireless routers operate using the 192.168.1.1 IP?
Certainly no, given that 192.168.1.1 is definitely a non-public IPv4 address, any type of laptop or computer, modem, switch, or another web system might be devised to work with this unique IP. Nonetheless, it's not in most cases advisable because there are lots of products which default to 192.168.1.1 which in turn interaction issues can occur soon after from many different products utilizing the same IP. It's also really important to consider that a single network equipment might have just one single Ip, if you own numerous units using private IP address, basically at least one has to be adjusted to an alternative location.